xref: /freebsd/sys/contrib/dev/rtw89/regd.c (revision 6d67aabd63555ab62a2f2b7f52a75ef100a2fe75)
18e93258fSBjoern A. Zeeb // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
28e93258fSBjoern A. Zeeb /* Copyright(c) 2019-2020  Realtek Corporation
38e93258fSBjoern A. Zeeb  */
48e93258fSBjoern A. Zeeb 
5e2340276SBjoern A. Zeeb #include "acpi.h"
68e93258fSBjoern A. Zeeb #include "debug.h"
78e93258fSBjoern A. Zeeb #include "ps.h"
8e2340276SBjoern A. Zeeb #include "util.h"
98e93258fSBjoern A. Zeeb 
108e93258fSBjoern A. Zeeb #define COUNTRY_REGD(_alpha2, _txpwr_regd...) \
118e93258fSBjoern A. Zeeb 	{.alpha2 = (_alpha2), \
128e93258fSBjoern A. Zeeb 	 .txpwr_regd = {_txpwr_regd}, \
138e93258fSBjoern A. Zeeb 	}
148e93258fSBjoern A. Zeeb 
15e2340276SBjoern A. Zeeb static const struct rtw89_regd rtw89_ww_regd =
16*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("00", RTW89_WW, RTW89_WW, RTW89_WW);
178e93258fSBjoern A. Zeeb 
18e2340276SBjoern A. Zeeb static const struct rtw89_regd rtw89_regd_map[] = {
19*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC),
20e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
218e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
228e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE),
23e2340276SBjoern A. Zeeb 	COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
248e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
258e93258fSBjoern A. Zeeb 	COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA),
26e2340276SBjoern A. Zeeb 	COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC),
27e2340276SBjoern A. Zeeb 	COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC),
288e93258fSBjoern A. Zeeb 	COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
29*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC),
308e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA),
318e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA),
328e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA),
33e2340276SBjoern A. Zeeb 	COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC),
348e93258fSBjoern A. Zeeb 	COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC),
358e93258fSBjoern A. Zeeb 	COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA),
368e93258fSBjoern A. Zeeb 	COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA),
378e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PR", RTW89_FCC, RTW89_FCC, RTW89_NA),
388e93258fSBjoern A. Zeeb 	COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_NA),
398e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
408e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
418e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
428e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
438e93258fSBjoern A. Zeeb 	COUNTRY_REGD("DK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
448e93258fSBjoern A. Zeeb 	COUNTRY_REGD("EE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
458e93258fSBjoern A. Zeeb 	COUNTRY_REGD("FI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
468e93258fSBjoern A. Zeeb 	COUNTRY_REGD("FR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
478e93258fSBjoern A. Zeeb 	COUNTRY_REGD("DE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
488e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
498e93258fSBjoern A. Zeeb 	COUNTRY_REGD("HU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
508e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
518e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
528e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
538e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LV", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
548e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
558e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
568e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
578e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
588e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MC", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
598e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
608e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
618e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
628e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
638e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
648e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
658e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ES", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
668e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
678e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
688e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK),
698e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
70e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
71e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
728e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
73e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
74e2340276SBjoern A. Zeeb 	COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
758e93258fSBjoern A. Zeeb 	COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
76e2340276SBjoern A. Zeeb 	COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
778e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
78e2340276SBjoern A. Zeeb 	COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
79e2340276SBjoern A. Zeeb 	COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
808e93258fSBjoern A. Zeeb 	COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
81e2340276SBjoern A. Zeeb 	COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
82e2340276SBjoern A. Zeeb 	COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
83e2340276SBjoern A. Zeeb 	COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
84*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
858e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
868e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
87e2340276SBjoern A. Zeeb 	COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
888e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
898e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
908e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
918e93258fSBjoern A. Zeeb 	COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
928e93258fSBjoern A. Zeeb 	COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR),
93e2340276SBjoern A. Zeeb 	COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
948e93258fSBjoern A. Zeeb 	COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
95e2340276SBjoern A. Zeeb 	COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
968e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
97e2340276SBjoern A. Zeeb 	COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
988e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
99*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
100e2340276SBjoern A. Zeeb 	COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1018e93258fSBjoern A. Zeeb 	COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE),
1028e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1038e93258fSBjoern A. Zeeb 	COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1048e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1058e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1068e93258fSBjoern A. Zeeb 	COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1078e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN),
108e2340276SBjoern A. Zeeb 	COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1098e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1108e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1118e93258fSBjoern A. Zeeb 	COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC),
112e2340276SBjoern A. Zeeb 	COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1138e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1148e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
115*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1168e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
117*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI),
118*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_THAILAND),
1198e93258fSBjoern A. Zeeb 	COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
120e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
121e2340276SBjoern A. Zeeb 	COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
122e2340276SBjoern A. Zeeb 	COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1238e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC),
124e2340276SBjoern A. Zeeb 	COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK),
125e2340276SBjoern A. Zeeb 	COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
126e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1278e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA),
1288e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1298e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
130e2340276SBjoern A. Zeeb 	COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1318e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA),
1328e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1338e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
134e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1358e93258fSBjoern A. Zeeb 	COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
136e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
137e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
138e2340276SBjoern A. Zeeb 	COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC),
139e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC),
140e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1418e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1428e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA),
1438e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
144e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1458e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
146e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1478e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1488e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
149e2340276SBjoern A. Zeeb 	COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1508e93258fSBjoern A. Zeeb 	COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
151*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1528e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
153e2340276SBjoern A. Zeeb 	COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1548e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1558e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
156e2340276SBjoern A. Zeeb 	COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1578e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
158e2340276SBjoern A. Zeeb 	COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1598e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
160e2340276SBjoern A. Zeeb 	COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
161e2340276SBjoern A. Zeeb 	COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1628e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1638e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1648e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1658e93258fSBjoern A. Zeeb 	COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
166e2340276SBjoern A. Zeeb 	COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
167*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA),
168e2340276SBjoern A. Zeeb 	COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1698e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1708e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1718e93258fSBjoern A. Zeeb 	COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1728e93258fSBjoern A. Zeeb 	COUNTRY_REGD("FO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1738e93258fSBjoern A. Zeeb 	COUNTRY_REGD("FJ", RTW89_FCC, RTW89_FCC, RTW89_NA),
1748e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1758e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1768e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1778e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
178e2340276SBjoern A. Zeeb 	COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1798e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1808e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1818e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
182e2340276SBjoern A. Zeeb 	COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1838e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1848e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA),
1858e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
186e2340276SBjoern A. Zeeb 	COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1878e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
188*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_NA),
189*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_FCC),
1908e93258fSBjoern A. Zeeb 	COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
1918e93258fSBjoern A. Zeeb 	COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1928e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1938e93258fSBjoern A. Zeeb 	COUNTRY_REGD("JE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1948e93258fSBjoern A. Zeeb 	COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
195*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
196*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
1978e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1988e93258fSBjoern A. Zeeb 	COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
1998e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
200e2340276SBjoern A. Zeeb 	COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2018e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2028e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2038e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2048e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA),
2058e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2068e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
207e2340276SBjoern A. Zeeb 	COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2088e93258fSBjoern A. Zeeb 	COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2098e93258fSBjoern A. Zeeb 	COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA),
210e2340276SBjoern A. Zeeb 	COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
211*6d67aabdSBjoern A. Zeeb 	COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2128e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2138e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2148e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NP", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2158e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NC", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2168e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2178e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NU", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
2188e93258fSBjoern A. Zeeb 	COUNTRY_REGD("NF", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
2198e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_NA),
2208e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_NA),
2218e93258fSBjoern A. Zeeb 	COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2228e93258fSBjoern A. Zeeb 	COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2238e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
224e2340276SBjoern A. Zeeb 	COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
225e2340276SBjoern A. Zeeb 	COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC),
2268e93258fSBjoern A. Zeeb 	COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA),
2278e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA),
2288e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2298e93258fSBjoern A. Zeeb 	COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA),
2308e93258fSBjoern A. Zeeb 	COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA),
2318e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
232e2340276SBjoern A. Zeeb 	COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2338e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA),
234e2340276SBjoern A. Zeeb 	COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2358e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2368e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2378e93258fSBjoern A. Zeeb 	COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
238e2340276SBjoern A. Zeeb 	COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
2398e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2408e93258fSBjoern A. Zeeb 	COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
241e2340276SBjoern A. Zeeb 	COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2428e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
243e2340276SBjoern A. Zeeb 	COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2448e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
2458e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2468e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2478e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TC", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2488e93258fSBjoern A. Zeeb 	COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA),
2498e93258fSBjoern A. Zeeb 	COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2508e93258fSBjoern A. Zeeb 	COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA),
251e2340276SBjoern A. Zeeb 	COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
2528e93258fSBjoern A. Zeeb 	COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2538e93258fSBjoern A. Zeeb 	COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2548e93258fSBjoern A. Zeeb 	COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2558e93258fSBjoern A. Zeeb 	COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2568e93258fSBjoern A. Zeeb 	COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2578e93258fSBjoern A. Zeeb 	COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
2588e93258fSBjoern A. Zeeb };
2598e93258fSBjoern A. Zeeb 
260*6d67aabdSBjoern A. Zeeb static const char rtw89_alpha2_list_eu[][3] = {
261*6d67aabdSBjoern A. Zeeb 	"AT",
262*6d67aabdSBjoern A. Zeeb 	"BE",
263*6d67aabdSBjoern A. Zeeb 	"CY",
264*6d67aabdSBjoern A. Zeeb 	"CZ",
265*6d67aabdSBjoern A. Zeeb 	"DK",
266*6d67aabdSBjoern A. Zeeb 	"EE",
267*6d67aabdSBjoern A. Zeeb 	"FI",
268*6d67aabdSBjoern A. Zeeb 	"FR",
269*6d67aabdSBjoern A. Zeeb 	"DE",
270*6d67aabdSBjoern A. Zeeb 	"GR",
271*6d67aabdSBjoern A. Zeeb 	"HU",
272*6d67aabdSBjoern A. Zeeb 	"IS",
273*6d67aabdSBjoern A. Zeeb 	"IE",
274*6d67aabdSBjoern A. Zeeb 	"IT",
275*6d67aabdSBjoern A. Zeeb 	"LV",
276*6d67aabdSBjoern A. Zeeb 	"LI",
277*6d67aabdSBjoern A. Zeeb 	"LT",
278*6d67aabdSBjoern A. Zeeb 	"LU",
279*6d67aabdSBjoern A. Zeeb 	"MT",
280*6d67aabdSBjoern A. Zeeb 	"MC",
281*6d67aabdSBjoern A. Zeeb 	"NL",
282*6d67aabdSBjoern A. Zeeb 	"NO",
283*6d67aabdSBjoern A. Zeeb 	"PL",
284*6d67aabdSBjoern A. Zeeb 	"PT",
285*6d67aabdSBjoern A. Zeeb 	"SK",
286*6d67aabdSBjoern A. Zeeb 	"SI",
287*6d67aabdSBjoern A. Zeeb 	"ES",
288*6d67aabdSBjoern A. Zeeb 	"SE",
289*6d67aabdSBjoern A. Zeeb 	"CH",
290*6d67aabdSBjoern A. Zeeb 	"BG",
291*6d67aabdSBjoern A. Zeeb 	"HR",
292*6d67aabdSBjoern A. Zeeb 	"RO",
293*6d67aabdSBjoern A. Zeeb };
294*6d67aabdSBjoern A. Zeeb 
295*6d67aabdSBjoern A. Zeeb static const struct rtw89_regd *rtw89_regd_find_reg_by_name(const char *alpha2)
2968e93258fSBjoern A. Zeeb {
2978e93258fSBjoern A. Zeeb 	u32 i;
2988e93258fSBjoern A. Zeeb 
2998e93258fSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
3008e93258fSBjoern A. Zeeb 		if (!memcmp(rtw89_regd_map[i].alpha2, alpha2, 2))
3018e93258fSBjoern A. Zeeb 			return &rtw89_regd_map[i];
3028e93258fSBjoern A. Zeeb 	}
3038e93258fSBjoern A. Zeeb 
3048e93258fSBjoern A. Zeeb 	return &rtw89_ww_regd;
3058e93258fSBjoern A. Zeeb }
3068e93258fSBjoern A. Zeeb 
307e2340276SBjoern A. Zeeb static bool rtw89_regd_is_ww(const struct rtw89_regd *regd)
3088e93258fSBjoern A. Zeeb {
3098e93258fSBjoern A. Zeeb 	return regd == &rtw89_ww_regd;
3108e93258fSBjoern A. Zeeb }
3118e93258fSBjoern A. Zeeb 
312*6d67aabdSBjoern A. Zeeb static u8 rtw89_regd_get_index(const struct rtw89_regd *regd)
313*6d67aabdSBjoern A. Zeeb {
314*6d67aabdSBjoern A. Zeeb 	BUILD_BUG_ON(ARRAY_SIZE(rtw89_regd_map) > RTW89_REGD_MAX_COUNTRY_NUM);
315*6d67aabdSBjoern A. Zeeb 
316*6d67aabdSBjoern A. Zeeb 	if (rtw89_regd_is_ww(regd))
317*6d67aabdSBjoern A. Zeeb 		return RTW89_REGD_MAX_COUNTRY_NUM;
318*6d67aabdSBjoern A. Zeeb 
319*6d67aabdSBjoern A. Zeeb 	return regd - rtw89_regd_map;
320*6d67aabdSBjoern A. Zeeb }
321*6d67aabdSBjoern A. Zeeb 
322*6d67aabdSBjoern A. Zeeb static u8 rtw89_regd_get_index_by_name(const char *alpha2)
323*6d67aabdSBjoern A. Zeeb {
324*6d67aabdSBjoern A. Zeeb 	const struct rtw89_regd *regd;
325*6d67aabdSBjoern A. Zeeb 
326*6d67aabdSBjoern A. Zeeb 	regd = rtw89_regd_find_reg_by_name(alpha2);
327*6d67aabdSBjoern A. Zeeb 	return rtw89_regd_get_index(regd);
328*6d67aabdSBjoern A. Zeeb }
329*6d67aabdSBjoern A. Zeeb 
3308e93258fSBjoern A. Zeeb #define rtw89_debug_regd(_dev, _regd, _desc, _argv...) \
3318e93258fSBjoern A. Zeeb do { \
3328e93258fSBjoern A. Zeeb 	typeof(_regd) __r = _regd; \
3338e93258fSBjoern A. Zeeb 	rtw89_debug(_dev, RTW89_DBG_REGD, _desc \
3348e93258fSBjoern A. Zeeb 		    ": %c%c: mapping txregd to {2g: %d, 5g: %d, 6g: %d}\n", \
3358e93258fSBjoern A. Zeeb 		    ##_argv, __r->alpha2[0], __r->alpha2[1], \
3368e93258fSBjoern A. Zeeb 		    __r->txpwr_regd[RTW89_BAND_2G], \
3378e93258fSBjoern A. Zeeb 		    __r->txpwr_regd[RTW89_BAND_5G], \
3388e93258fSBjoern A. Zeeb 		    __r->txpwr_regd[RTW89_BAND_6G]); \
3398e93258fSBjoern A. Zeeb } while (0)
3408e93258fSBjoern A. Zeeb 
341e2340276SBjoern A. Zeeb static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev,
342e2340276SBjoern A. Zeeb 				   struct wiphy *wiphy)
343e2340276SBjoern A. Zeeb {
344*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
345e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
346e2340276SBjoern A. Zeeb 	struct ieee80211_supported_band *sband;
347*6d67aabdSBjoern A. Zeeb 	struct rtw89_acpi_dsm_result res = {};
348*6d67aabdSBjoern A. Zeeb 	bool enable_by_fcc;
349*6d67aabdSBjoern A. Zeeb 	bool enable_by_ic;
350e2340276SBjoern A. Zeeb 	int ret;
351e2340276SBjoern A. Zeeb 	u8 val;
352*6d67aabdSBjoern A. Zeeb 	int i;
353e2340276SBjoern A. Zeeb 
354e2340276SBjoern A. Zeeb 	sband = wiphy->bands[NL80211_BAND_5GHZ];
355e2340276SBjoern A. Zeeb 	if (!sband)
356e2340276SBjoern A. Zeeb 		return;
357e2340276SBjoern A. Zeeb 
358*6d67aabdSBjoern A. Zeeb 	if (!chip->support_unii4) {
359*6d67aabdSBjoern A. Zeeb 		sband->n_channels -= RTW89_5GHZ_UNII4_CHANNEL_NUM;
360*6d67aabdSBjoern A. Zeeb 		return;
361*6d67aabdSBjoern A. Zeeb 	}
362*6d67aabdSBjoern A. Zeeb 
363*6d67aabdSBjoern A. Zeeb 	bitmap_fill(regulatory->block_unii4, RTW89_REGD_MAX_COUNTRY_NUM);
364*6d67aabdSBjoern A. Zeeb 
365*6d67aabdSBjoern A. Zeeb 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_UNII4_SUP, &res);
366*6d67aabdSBjoern A. Zeeb 	if (ret) {
367*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
368*6d67aabdSBjoern A. Zeeb 			    "acpi: cannot eval unii 4: %d\n", ret);
369*6d67aabdSBjoern A. Zeeb 		enable_by_fcc = true;
370*6d67aabdSBjoern A. Zeeb 		enable_by_ic = false;
371*6d67aabdSBjoern A. Zeeb 		goto bottom;
372*6d67aabdSBjoern A. Zeeb 	}
373*6d67aabdSBjoern A. Zeeb 
374*6d67aabdSBjoern A. Zeeb 	val = res.u.value;
375*6d67aabdSBjoern A. Zeeb 	enable_by_fcc = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_FCC);
376*6d67aabdSBjoern A. Zeeb 	enable_by_ic = u8_get_bits(val, RTW89_ACPI_CONF_UNII4_IC);
377*6d67aabdSBjoern A. Zeeb 
378*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_REGD,
379*6d67aabdSBjoern A. Zeeb 		    "acpi: eval if allow unii-4: 0x%x\n", val);
380*6d67aabdSBjoern A. Zeeb 
381*6d67aabdSBjoern A. Zeeb bottom:
382*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
383*6d67aabdSBjoern A. Zeeb 		const struct rtw89_regd *regd = &rtw89_regd_map[i];
384*6d67aabdSBjoern A. Zeeb 
385*6d67aabdSBjoern A. Zeeb 		switch (regd->txpwr_regd[RTW89_BAND_5G]) {
386*6d67aabdSBjoern A. Zeeb 		case RTW89_FCC:
387*6d67aabdSBjoern A. Zeeb 			if (enable_by_fcc)
388*6d67aabdSBjoern A. Zeeb 				clear_bit(i, regulatory->block_unii4);
389*6d67aabdSBjoern A. Zeeb 			break;
390*6d67aabdSBjoern A. Zeeb 		case RTW89_IC:
391*6d67aabdSBjoern A. Zeeb 			if (enable_by_ic)
392*6d67aabdSBjoern A. Zeeb 				clear_bit(i, regulatory->block_unii4);
393*6d67aabdSBjoern A. Zeeb 			break;
394*6d67aabdSBjoern A. Zeeb 		default:
395*6d67aabdSBjoern A. Zeeb 			break;
396*6d67aabdSBjoern A. Zeeb 		}
397*6d67aabdSBjoern A. Zeeb 	}
398*6d67aabdSBjoern A. Zeeb }
399*6d67aabdSBjoern A. Zeeb 
400*6d67aabdSBjoern A. Zeeb static void __rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev, bool block,
401*6d67aabdSBjoern A. Zeeb 					   const char *alpha2)
402*6d67aabdSBjoern A. Zeeb {
403*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
404*6d67aabdSBjoern A. Zeeb 	u8 index;
405*6d67aabdSBjoern A. Zeeb 
406*6d67aabdSBjoern A. Zeeb 	index = rtw89_regd_get_index_by_name(alpha2);
407*6d67aabdSBjoern A. Zeeb 	if (index == RTW89_REGD_MAX_COUNTRY_NUM) {
408*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD, "%s: unknown alpha2 %c%c\n",
409*6d67aabdSBjoern A. Zeeb 			    __func__, alpha2[0], alpha2[1]);
410*6d67aabdSBjoern A. Zeeb 		return;
411*6d67aabdSBjoern A. Zeeb 	}
412*6d67aabdSBjoern A. Zeeb 
413*6d67aabdSBjoern A. Zeeb 	if (block)
414*6d67aabdSBjoern A. Zeeb 		set_bit(index, regulatory->block_6ghz);
415*6d67aabdSBjoern A. Zeeb 	else
416*6d67aabdSBjoern A. Zeeb 		clear_bit(index, regulatory->block_6ghz);
417*6d67aabdSBjoern A. Zeeb }
418*6d67aabdSBjoern A. Zeeb 
419*6d67aabdSBjoern A. Zeeb static void rtw89_regd_setup_policy_6ghz(struct rtw89_dev *rtwdev)
420*6d67aabdSBjoern A. Zeeb {
421*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
422*6d67aabdSBjoern A. Zeeb 	const struct rtw89_acpi_country_code *country;
423*6d67aabdSBjoern A. Zeeb 	const struct rtw89_acpi_policy_6ghz *ptr;
424*6d67aabdSBjoern A. Zeeb 	struct rtw89_acpi_dsm_result res = {};
425*6d67aabdSBjoern A. Zeeb 	bool to_block;
426*6d67aabdSBjoern A. Zeeb 	int i, j;
427*6d67aabdSBjoern A. Zeeb 	int ret;
428*6d67aabdSBjoern A. Zeeb 
429*6d67aabdSBjoern A. Zeeb 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_BP, &res);
430*6d67aabdSBjoern A. Zeeb 	if (ret) {
431*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
432*6d67aabdSBjoern A. Zeeb 			    "acpi: cannot eval policy 6ghz: %d\n", ret);
433*6d67aabdSBjoern A. Zeeb 		return;
434*6d67aabdSBjoern A. Zeeb 	}
435*6d67aabdSBjoern A. Zeeb 
436*6d67aabdSBjoern A. Zeeb 	ptr = res.u.policy_6ghz;
437*6d67aabdSBjoern A. Zeeb 
438*6d67aabdSBjoern A. Zeeb 	switch (ptr->policy_mode) {
439*6d67aabdSBjoern A. Zeeb 	case RTW89_ACPI_POLICY_BLOCK:
440*6d67aabdSBjoern A. Zeeb 		to_block = true;
441*6d67aabdSBjoern A. Zeeb 		break;
442*6d67aabdSBjoern A. Zeeb 	case RTW89_ACPI_POLICY_ALLOW:
443*6d67aabdSBjoern A. Zeeb 		to_block = false;
444*6d67aabdSBjoern A. Zeeb 		/* only below list is allowed; block all first */
445*6d67aabdSBjoern A. Zeeb 		bitmap_fill(regulatory->block_6ghz, RTW89_REGD_MAX_COUNTRY_NUM);
446*6d67aabdSBjoern A. Zeeb 		break;
447*6d67aabdSBjoern A. Zeeb 	default:
448*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
449*6d67aabdSBjoern A. Zeeb 			    "%s: unknown policy mode: %d\n", __func__,
450*6d67aabdSBjoern A. Zeeb 			    ptr->policy_mode);
451*6d67aabdSBjoern A. Zeeb 		goto out;
452*6d67aabdSBjoern A. Zeeb 	}
453*6d67aabdSBjoern A. Zeeb 
454*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < ptr->country_count; i++) {
455*6d67aabdSBjoern A. Zeeb 		country = &ptr->country_list[i];
456*6d67aabdSBjoern A. Zeeb 		if (memcmp("EU", country->alpha2, 2) != 0) {
457*6d67aabdSBjoern A. Zeeb 			__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
458*6d67aabdSBjoern A. Zeeb 						       country->alpha2);
459*6d67aabdSBjoern A. Zeeb 			continue;
460*6d67aabdSBjoern A. Zeeb 		}
461*6d67aabdSBjoern A. Zeeb 
462*6d67aabdSBjoern A. Zeeb 		for (j = 0; j < ARRAY_SIZE(rtw89_alpha2_list_eu); j++)
463*6d67aabdSBjoern A. Zeeb 			__rtw89_regd_setup_policy_6ghz(rtwdev, to_block,
464*6d67aabdSBjoern A. Zeeb 						       rtw89_alpha2_list_eu[j]);
465*6d67aabdSBjoern A. Zeeb 	}
466*6d67aabdSBjoern A. Zeeb 
467*6d67aabdSBjoern A. Zeeb out:
468*6d67aabdSBjoern A. Zeeb 	kfree(ptr);
469*6d67aabdSBjoern A. Zeeb }
470*6d67aabdSBjoern A. Zeeb 
471*6d67aabdSBjoern A. Zeeb static void rtw89_regd_setup_policy_6ghz_sp(struct rtw89_dev *rtwdev)
472*6d67aabdSBjoern A. Zeeb {
473*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
474*6d67aabdSBjoern A. Zeeb 	const struct rtw89_acpi_policy_6ghz_sp *ptr;
475*6d67aabdSBjoern A. Zeeb 	struct rtw89_acpi_dsm_result res = {};
476*6d67aabdSBjoern A. Zeeb 	bool enable_by_us;
477*6d67aabdSBjoern A. Zeeb 	int ret;
478*6d67aabdSBjoern A. Zeeb 	int i;
479*6d67aabdSBjoern A. Zeeb 
480*6d67aabdSBjoern A. Zeeb 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6GHZ_SP_SUP, &res);
481*6d67aabdSBjoern A. Zeeb 	if (ret) {
482*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
483*6d67aabdSBjoern A. Zeeb 			    "acpi: cannot eval policy 6ghz-sp: %d\n", ret);
484*6d67aabdSBjoern A. Zeeb 		return;
485*6d67aabdSBjoern A. Zeeb 	}
486*6d67aabdSBjoern A. Zeeb 
487*6d67aabdSBjoern A. Zeeb 	ptr = res.u.policy_6ghz_sp;
488*6d67aabdSBjoern A. Zeeb 
489*6d67aabdSBjoern A. Zeeb 	switch (ptr->override) {
490*6d67aabdSBjoern A. Zeeb 	default:
491*6d67aabdSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
492*6d67aabdSBjoern A. Zeeb 			    "%s: unknown override case: %d\n", __func__,
493*6d67aabdSBjoern A. Zeeb 			    ptr->override);
494*6d67aabdSBjoern A. Zeeb 		fallthrough;
495*6d67aabdSBjoern A. Zeeb 	case 0:
496*6d67aabdSBjoern A. Zeeb 		goto out;
497*6d67aabdSBjoern A. Zeeb 	case 1:
498*6d67aabdSBjoern A. Zeeb 		break;
499*6d67aabdSBjoern A. Zeeb 	}
500*6d67aabdSBjoern A. Zeeb 
501*6d67aabdSBjoern A. Zeeb 	bitmap_fill(regulatory->block_6ghz_sp, RTW89_REGD_MAX_COUNTRY_NUM);
502*6d67aabdSBjoern A. Zeeb 
503*6d67aabdSBjoern A. Zeeb 	enable_by_us = u8_get_bits(ptr->conf, RTW89_ACPI_CONF_6GHZ_SP_US);
504*6d67aabdSBjoern A. Zeeb 
505*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < ARRAY_SIZE(rtw89_regd_map); i++) {
506*6d67aabdSBjoern A. Zeeb 		const struct rtw89_regd *tmp = &rtw89_regd_map[i];
507*6d67aabdSBjoern A. Zeeb 
508*6d67aabdSBjoern A. Zeeb 		if (enable_by_us && memcmp(tmp->alpha2, "US", 2) == 0)
509*6d67aabdSBjoern A. Zeeb 			clear_bit(i, regulatory->block_6ghz_sp);
510*6d67aabdSBjoern A. Zeeb 	}
511*6d67aabdSBjoern A. Zeeb 
512*6d67aabdSBjoern A. Zeeb out:
513*6d67aabdSBjoern A. Zeeb 	kfree(ptr);
514e2340276SBjoern A. Zeeb }
515e2340276SBjoern A. Zeeb 
516e2340276SBjoern A. Zeeb static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy)
517e2340276SBjoern A. Zeeb {
518e2340276SBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
519e2340276SBjoern A. Zeeb 	bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ);
520e2340276SBjoern A. Zeeb 	bool regd_allow_6ghz = chip_support_6ghz;
521e2340276SBjoern A. Zeeb 	struct ieee80211_supported_band *sband;
522*6d67aabdSBjoern A. Zeeb 	struct rtw89_acpi_dsm_result res = {};
523e2340276SBjoern A. Zeeb 	int ret;
524e2340276SBjoern A. Zeeb 	u8 val;
525e2340276SBjoern A. Zeeb 
526e2340276SBjoern A. Zeeb 	if (!chip_support_6ghz)
527e2340276SBjoern A. Zeeb 		goto bottom;
528e2340276SBjoern A. Zeeb 
529*6d67aabdSBjoern A. Zeeb 	ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &res);
530e2340276SBjoern A. Zeeb 	if (ret) {
531e2340276SBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
532e2340276SBjoern A. Zeeb 			    "acpi: cannot eval 6ghz: %d\n", ret);
533e2340276SBjoern A. Zeeb 		goto bottom;
534e2340276SBjoern A. Zeeb 	}
535e2340276SBjoern A. Zeeb 
536*6d67aabdSBjoern A. Zeeb 	val = res.u.value;
537*6d67aabdSBjoern A. Zeeb 
538e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_REGD,
539e2340276SBjoern A. Zeeb 		    "acpi: eval if disallow 6ghz: %d\n", val);
540e2340276SBjoern A. Zeeb 
541e2340276SBjoern A. Zeeb 	switch (val) {
542e2340276SBjoern A. Zeeb 	case 0:
543e2340276SBjoern A. Zeeb 		regd_allow_6ghz = true;
544e2340276SBjoern A. Zeeb 		break;
545e2340276SBjoern A. Zeeb 	case 1:
546e2340276SBjoern A. Zeeb 		regd_allow_6ghz = false;
547e2340276SBjoern A. Zeeb 		break;
548e2340276SBjoern A. Zeeb 	default:
549e2340276SBjoern A. Zeeb 		break;
550e2340276SBjoern A. Zeeb 	}
551e2340276SBjoern A. Zeeb 
552e2340276SBjoern A. Zeeb bottom:
553e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n",
554e2340276SBjoern A. Zeeb 		    regd_allow_6ghz);
555e2340276SBjoern A. Zeeb 
556*6d67aabdSBjoern A. Zeeb 	if (regd_allow_6ghz) {
557*6d67aabdSBjoern A. Zeeb 		rtw89_regd_setup_policy_6ghz(rtwdev);
558*6d67aabdSBjoern A. Zeeb 		rtw89_regd_setup_policy_6ghz_sp(rtwdev);
559e2340276SBjoern A. Zeeb 		return;
560*6d67aabdSBjoern A. Zeeb 	}
561e2340276SBjoern A. Zeeb 
562e2340276SBjoern A. Zeeb 	sband = wiphy->bands[NL80211_BAND_6GHZ];
563e2340276SBjoern A. Zeeb 	if (!sband)
564e2340276SBjoern A. Zeeb 		return;
565e2340276SBjoern A. Zeeb 
566e2340276SBjoern A. Zeeb 	wiphy->bands[NL80211_BAND_6GHZ] = NULL;
567*6d67aabdSBjoern A. Zeeb 	kfree((__force void *)sband->iftype_data);
568e2340276SBjoern A. Zeeb 	kfree(sband);
569e2340276SBjoern A. Zeeb }
570e2340276SBjoern A. Zeeb 
571e2340276SBjoern A. Zeeb int rtw89_regd_setup(struct rtw89_dev *rtwdev)
572e2340276SBjoern A. Zeeb {
573e2340276SBjoern A. Zeeb 	struct wiphy *wiphy = rtwdev->hw->wiphy;
574e2340276SBjoern A. Zeeb 
575e2340276SBjoern A. Zeeb 	if (!wiphy)
576e2340276SBjoern A. Zeeb 		return -EINVAL;
577e2340276SBjoern A. Zeeb 
578e2340276SBjoern A. Zeeb 	rtw89_regd_setup_unii4(rtwdev, wiphy);
579e2340276SBjoern A. Zeeb 	rtw89_regd_setup_6ghz(rtwdev, wiphy);
580e2340276SBjoern A. Zeeb 
581e2340276SBjoern A. Zeeb 	wiphy->reg_notifier = rtw89_regd_notifier;
582e2340276SBjoern A. Zeeb 	return 0;
583e2340276SBjoern A. Zeeb }
584e2340276SBjoern A. Zeeb 
5858e93258fSBjoern A. Zeeb int rtw89_regd_init(struct rtw89_dev *rtwdev,
5868e93258fSBjoern A. Zeeb 		    void (*reg_notifier)(struct wiphy *wiphy,
5878e93258fSBjoern A. Zeeb 					 struct regulatory_request *request))
5888e93258fSBjoern A. Zeeb {
589e2340276SBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
590e2340276SBjoern A. Zeeb 	const struct rtw89_regd *chip_regd;
5918e93258fSBjoern A. Zeeb 	struct wiphy *wiphy = rtwdev->hw->wiphy;
5928e93258fSBjoern A. Zeeb 	int ret;
5938e93258fSBjoern A. Zeeb 
594e2340276SBjoern A. Zeeb 	regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
595e2340276SBjoern A. Zeeb 
5968e93258fSBjoern A. Zeeb 	if (!wiphy)
5978e93258fSBjoern A. Zeeb 		return -EINVAL;
5988e93258fSBjoern A. Zeeb 
5998e93258fSBjoern A. Zeeb 	chip_regd = rtw89_regd_find_reg_by_name(rtwdev->efuse.country_code);
6008e93258fSBjoern A. Zeeb #if defined(__FreeBSD__)
601e2340276SBjoern A. Zeeb 	rtwdev->regulatory.regd = chip_regd;
6028e93258fSBjoern A. Zeeb #endif
6038e93258fSBjoern A. Zeeb 	if (!rtw89_regd_is_ww(chip_regd)) {
6048e93258fSBjoern A. Zeeb #if defined(__linux__)
605e2340276SBjoern A. Zeeb 		rtwdev->regulatory.regd = chip_regd;
6068e93258fSBjoern A. Zeeb #endif
6078e93258fSBjoern A. Zeeb 		/* Ignore country ie if there is a country domain programmed in chip */
6088e93258fSBjoern A. Zeeb 		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
6098e93258fSBjoern A. Zeeb 		wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
6108e93258fSBjoern A. Zeeb 
611e2340276SBjoern A. Zeeb 		ret = regulatory_hint(rtwdev->hw->wiphy,
612e2340276SBjoern A. Zeeb 				      rtwdev->regulatory.regd->alpha2);
6138e93258fSBjoern A. Zeeb 		if (ret)
6148e93258fSBjoern A. Zeeb 			rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret);
6158e93258fSBjoern A. Zeeb 
6168e93258fSBjoern A. Zeeb 		rtw89_debug_regd(rtwdev, chip_regd, "efuse country code");
6178e93258fSBjoern A. Zeeb 		return 0;
6188e93258fSBjoern A. Zeeb 	}
6198e93258fSBjoern A. Zeeb 
620e2340276SBjoern A. Zeeb 	rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
6218e93258fSBjoern A. Zeeb 			 "worldwide roaming chip, follow the setting of stack");
6228e93258fSBjoern A. Zeeb 	return 0;
6238e93258fSBjoern A. Zeeb }
6248e93258fSBjoern A. Zeeb 
625*6d67aabdSBjoern A. Zeeb static void rtw89_regd_apply_policy_unii4(struct rtw89_dev *rtwdev,
626*6d67aabdSBjoern A. Zeeb 					  struct wiphy *wiphy)
627*6d67aabdSBjoern A. Zeeb {
628*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
629*6d67aabdSBjoern A. Zeeb 	const struct rtw89_chip_info *chip = rtwdev->chip;
630*6d67aabdSBjoern A. Zeeb 	const struct rtw89_regd *regd = regulatory->regd;
631*6d67aabdSBjoern A. Zeeb 	struct ieee80211_supported_band *sband;
632*6d67aabdSBjoern A. Zeeb 	u8 index;
633*6d67aabdSBjoern A. Zeeb 	int i;
634*6d67aabdSBjoern A. Zeeb 
635*6d67aabdSBjoern A. Zeeb 	sband = wiphy->bands[NL80211_BAND_5GHZ];
636*6d67aabdSBjoern A. Zeeb 	if (!sband)
637*6d67aabdSBjoern A. Zeeb 		return;
638*6d67aabdSBjoern A. Zeeb 
639*6d67aabdSBjoern A. Zeeb 	if (!chip->support_unii4)
640*6d67aabdSBjoern A. Zeeb 		return;
641*6d67aabdSBjoern A. Zeeb 
642*6d67aabdSBjoern A. Zeeb 	index = rtw89_regd_get_index(regd);
643*6d67aabdSBjoern A. Zeeb 	if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
644*6d67aabdSBjoern A. Zeeb 	    !test_bit(index, regulatory->block_unii4))
645*6d67aabdSBjoern A. Zeeb 		return;
646*6d67aabdSBjoern A. Zeeb 
647*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c unii-4 is blocked by policy\n",
648*6d67aabdSBjoern A. Zeeb 		    regd->alpha2[0], regd->alpha2[1]);
649*6d67aabdSBjoern A. Zeeb 
650*6d67aabdSBjoern A. Zeeb 	for (i = RTW89_5GHZ_UNII4_START_INDEX; i < sband->n_channels; i++)
651*6d67aabdSBjoern A. Zeeb 		sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
652*6d67aabdSBjoern A. Zeeb }
653*6d67aabdSBjoern A. Zeeb 
654*6d67aabdSBjoern A. Zeeb static void rtw89_regd_apply_policy_6ghz(struct rtw89_dev *rtwdev,
655*6d67aabdSBjoern A. Zeeb 					 struct wiphy *wiphy)
656*6d67aabdSBjoern A. Zeeb {
657*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
658*6d67aabdSBjoern A. Zeeb 	const struct rtw89_regd *regd = regulatory->regd;
659*6d67aabdSBjoern A. Zeeb 	struct ieee80211_supported_band *sband;
660*6d67aabdSBjoern A. Zeeb 	u8 index;
661*6d67aabdSBjoern A. Zeeb 	int i;
662*6d67aabdSBjoern A. Zeeb 
663*6d67aabdSBjoern A. Zeeb 	index = rtw89_regd_get_index(regd);
664*6d67aabdSBjoern A. Zeeb 	if (index != RTW89_REGD_MAX_COUNTRY_NUM &&
665*6d67aabdSBjoern A. Zeeb 	    !test_bit(index, regulatory->block_6ghz))
666*6d67aabdSBjoern A. Zeeb 		return;
667*6d67aabdSBjoern A. Zeeb 
668*6d67aabdSBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_REGD, "%c%c 6 GHz is blocked by policy\n",
669*6d67aabdSBjoern A. Zeeb 		    regd->alpha2[0], regd->alpha2[1]);
670*6d67aabdSBjoern A. Zeeb 
671*6d67aabdSBjoern A. Zeeb 	sband = wiphy->bands[NL80211_BAND_6GHZ];
672*6d67aabdSBjoern A. Zeeb 	if (!sband)
673*6d67aabdSBjoern A. Zeeb 		return;
674*6d67aabdSBjoern A. Zeeb 
675*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < sband->n_channels; i++)
676*6d67aabdSBjoern A. Zeeb 		sband->channels[i].flags |= IEEE80211_CHAN_DISABLED;
677*6d67aabdSBjoern A. Zeeb }
678*6d67aabdSBjoern A. Zeeb 
6798e93258fSBjoern A. Zeeb static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev,
6808e93258fSBjoern A. Zeeb 				      struct wiphy *wiphy,
6818e93258fSBjoern A. Zeeb 				      struct regulatory_request *request)
6828e93258fSBjoern A. Zeeb {
683e2340276SBjoern A. Zeeb 	rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(request->alpha2);
6848e93258fSBjoern A. Zeeb 	/* This notification might be set from the system of distros,
6858e93258fSBjoern A. Zeeb 	 * and it does not expect the regulatory will be modified by
6868e93258fSBjoern A. Zeeb 	 * connecting to an AP (i.e. country ie).
6878e93258fSBjoern A. Zeeb 	 */
6888e93258fSBjoern A. Zeeb 	if (request->initiator == NL80211_REGDOM_SET_BY_USER &&
689e2340276SBjoern A. Zeeb 	    !rtw89_regd_is_ww(rtwdev->regulatory.regd))
6908e93258fSBjoern A. Zeeb 		wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
6918e93258fSBjoern A. Zeeb 	else
6928e93258fSBjoern A. Zeeb 		wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE;
693*6d67aabdSBjoern A. Zeeb 
694*6d67aabdSBjoern A. Zeeb 	rtw89_regd_apply_policy_unii4(rtwdev, wiphy);
695*6d67aabdSBjoern A. Zeeb 	rtw89_regd_apply_policy_6ghz(rtwdev, wiphy);
6968e93258fSBjoern A. Zeeb }
6978e93258fSBjoern A. Zeeb 
6988e93258fSBjoern A. Zeeb void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
6998e93258fSBjoern A. Zeeb {
7008e93258fSBjoern A. Zeeb 	struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
7018e93258fSBjoern A. Zeeb 	struct rtw89_dev *rtwdev = hw->priv;
7028e93258fSBjoern A. Zeeb 
7038e93258fSBjoern A. Zeeb 	mutex_lock(&rtwdev->mutex);
7048e93258fSBjoern A. Zeeb 	rtw89_leave_ps_mode(rtwdev);
7058e93258fSBjoern A. Zeeb 
7068e93258fSBjoern A. Zeeb 	if (wiphy->regd) {
7078e93258fSBjoern A. Zeeb 		rtw89_debug(rtwdev, RTW89_DBG_REGD,
7088e93258fSBjoern A. Zeeb 			    "There is a country domain programmed in chip, ignore notifications\n");
7098e93258fSBjoern A. Zeeb 		goto exit;
7108e93258fSBjoern A. Zeeb 	}
7118e93258fSBjoern A. Zeeb 	rtw89_regd_notifier_apply(rtwdev, wiphy, request);
712e2340276SBjoern A. Zeeb 	rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd,
713e2340276SBjoern A. Zeeb 			 "get from initiator %d, alpha2",
7148e93258fSBjoern A. Zeeb 			 request->initiator);
7158e93258fSBjoern A. Zeeb 
7168e93258fSBjoern A. Zeeb 	rtw89_core_set_chip_txpwr(rtwdev);
7178e93258fSBjoern A. Zeeb 
7188e93258fSBjoern A. Zeeb exit:
7198e93258fSBjoern A. Zeeb 	mutex_unlock(&rtwdev->mutex);
7208e93258fSBjoern A. Zeeb }
721e2340276SBjoern A. Zeeb 
722*6d67aabdSBjoern A. Zeeb /* Maximum Transmit Power field (@raw) can be EIRP or PSD.
723*6d67aabdSBjoern A. Zeeb  * Both units are 0.5 dB-based. Return a constraint in dB.
724*6d67aabdSBjoern A. Zeeb  */
725*6d67aabdSBjoern A. Zeeb static s8 tpe_get_constraint(s8 raw)
726*6d67aabdSBjoern A. Zeeb {
727*6d67aabdSBjoern A. Zeeb 	const u8 hw_deviation = 3; /* unit: 0.5 dB */
728*6d67aabdSBjoern A. Zeeb 	const u8 antenna_gain = 10; /* unit: 0.5 dB */
729*6d67aabdSBjoern A. Zeeb 	const u8 array_gain = 6; /* unit: 0.5 dB */
730*6d67aabdSBjoern A. Zeeb 	const u8 offset = hw_deviation + antenna_gain + array_gain;
731*6d67aabdSBjoern A. Zeeb 
732*6d67aabdSBjoern A. Zeeb 	return (raw - offset) / 2;
733*6d67aabdSBjoern A. Zeeb }
734*6d67aabdSBjoern A. Zeeb 
735*6d67aabdSBjoern A. Zeeb static void tpe_intersect_constraint(struct rtw89_reg_6ghz_tpe *tpe, s8 cstr)
736*6d67aabdSBjoern A. Zeeb {
737*6d67aabdSBjoern A. Zeeb 	if (tpe->valid) {
738*6d67aabdSBjoern A. Zeeb 		tpe->constraint = min(tpe->constraint, cstr);
739*6d67aabdSBjoern A. Zeeb 		return;
740*6d67aabdSBjoern A. Zeeb 	}
741*6d67aabdSBjoern A. Zeeb 
742*6d67aabdSBjoern A. Zeeb 	tpe->constraint = cstr;
743*6d67aabdSBjoern A. Zeeb 	tpe->valid = true;
744*6d67aabdSBjoern A. Zeeb }
745*6d67aabdSBjoern A. Zeeb 
746*6d67aabdSBjoern A. Zeeb static void tpe_deal_with_eirp(struct rtw89_reg_6ghz_tpe *tpe,
747*6d67aabdSBjoern A. Zeeb 			       const struct ieee80211_parsed_tpe_eirp *eirp)
748*6d67aabdSBjoern A. Zeeb {
749*6d67aabdSBjoern A. Zeeb 	unsigned int i;
750*6d67aabdSBjoern A. Zeeb 	s8 cstr;
751*6d67aabdSBjoern A. Zeeb 
752*6d67aabdSBjoern A. Zeeb 	if (!eirp->valid)
753*6d67aabdSBjoern A. Zeeb 		return;
754*6d67aabdSBjoern A. Zeeb 
755*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < eirp->count; i++) {
756*6d67aabdSBjoern A. Zeeb 		cstr = tpe_get_constraint(eirp->power[i]);
757*6d67aabdSBjoern A. Zeeb 		tpe_intersect_constraint(tpe, cstr);
758*6d67aabdSBjoern A. Zeeb 	}
759*6d67aabdSBjoern A. Zeeb }
760*6d67aabdSBjoern A. Zeeb 
761*6d67aabdSBjoern A. Zeeb static s8 tpe_convert_psd_to_eirp(s8 psd)
762*6d67aabdSBjoern A. Zeeb {
763*6d67aabdSBjoern A. Zeeb 	static const unsigned int mlog20 = 1301;
764*6d67aabdSBjoern A. Zeeb 
765*6d67aabdSBjoern A. Zeeb 	return psd + 10 * mlog20 / 1000;
766*6d67aabdSBjoern A. Zeeb }
767*6d67aabdSBjoern A. Zeeb 
768*6d67aabdSBjoern A. Zeeb static void tpe_deal_with_psd(struct rtw89_reg_6ghz_tpe *tpe,
769*6d67aabdSBjoern A. Zeeb 			      const struct ieee80211_parsed_tpe_psd *psd)
770*6d67aabdSBjoern A. Zeeb {
771*6d67aabdSBjoern A. Zeeb 	unsigned int i;
772*6d67aabdSBjoern A. Zeeb 	s8 cstr_psd;
773*6d67aabdSBjoern A. Zeeb 	s8 cstr;
774*6d67aabdSBjoern A. Zeeb 
775*6d67aabdSBjoern A. Zeeb 	if (!psd->valid)
776*6d67aabdSBjoern A. Zeeb 		return;
777*6d67aabdSBjoern A. Zeeb 
778*6d67aabdSBjoern A. Zeeb 	for (i = 0; i < psd->count; i++) {
779*6d67aabdSBjoern A. Zeeb 		cstr_psd = tpe_get_constraint(psd->power[i]);
780*6d67aabdSBjoern A. Zeeb 		cstr = tpe_convert_psd_to_eirp(cstr_psd);
781*6d67aabdSBjoern A. Zeeb 		tpe_intersect_constraint(tpe, cstr);
782*6d67aabdSBjoern A. Zeeb 	}
783*6d67aabdSBjoern A. Zeeb }
784*6d67aabdSBjoern A. Zeeb 
785*6d67aabdSBjoern A. Zeeb static void rtw89_calculate_tpe(struct rtw89_dev *rtwdev,
786*6d67aabdSBjoern A. Zeeb 				struct rtw89_reg_6ghz_tpe *result_tpe,
787*6d67aabdSBjoern A. Zeeb 				const struct ieee80211_parsed_tpe *parsed_tpe)
788*6d67aabdSBjoern A. Zeeb {
789*6d67aabdSBjoern A. Zeeb 	static const u8 category = IEEE80211_TPE_CAT_6GHZ_DEFAULT;
790*6d67aabdSBjoern A. Zeeb 
791*6d67aabdSBjoern A. Zeeb 	tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_local[category]);
792*6d67aabdSBjoern A. Zeeb 	tpe_deal_with_eirp(result_tpe, &parsed_tpe->max_reg_client[category]);
793*6d67aabdSBjoern A. Zeeb 	tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_local[category]);
794*6d67aabdSBjoern A. Zeeb 	tpe_deal_with_psd(result_tpe, &parsed_tpe->psd_reg_client[category]);
795*6d67aabdSBjoern A. Zeeb }
796*6d67aabdSBjoern A. Zeeb 
797*6d67aabdSBjoern A. Zeeb static bool __rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev)
798e2340276SBjoern A. Zeeb {
799e2340276SBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
800*6d67aabdSBjoern A. Zeeb 	struct rtw89_reg_6ghz_tpe new = {};
801*6d67aabdSBjoern A. Zeeb 	struct rtw89_vif *rtwvif;
802*6d67aabdSBjoern A. Zeeb 	bool changed = false;
803*6d67aabdSBjoern A. Zeeb 
804*6d67aabdSBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
805*6d67aabdSBjoern A. Zeeb 		const struct rtw89_reg_6ghz_tpe *tmp;
806*6d67aabdSBjoern A. Zeeb 		const struct rtw89_chan *chan;
807*6d67aabdSBjoern A. Zeeb 
808*6d67aabdSBjoern A. Zeeb 		chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
809*6d67aabdSBjoern A. Zeeb 		if (chan->band_type != RTW89_BAND_6G)
810*6d67aabdSBjoern A. Zeeb 			continue;
811*6d67aabdSBjoern A. Zeeb 
812*6d67aabdSBjoern A. Zeeb 		tmp = &rtwvif->reg_6ghz_tpe;
813*6d67aabdSBjoern A. Zeeb 		if (!tmp->valid)
814*6d67aabdSBjoern A. Zeeb 			continue;
815*6d67aabdSBjoern A. Zeeb 
816*6d67aabdSBjoern A. Zeeb 		tpe_intersect_constraint(&new, tmp->constraint);
817*6d67aabdSBjoern A. Zeeb 	}
818*6d67aabdSBjoern A. Zeeb 
819*6d67aabdSBjoern A. Zeeb 	if (memcmp(&regulatory->reg_6ghz_tpe, &new,
820*6d67aabdSBjoern A. Zeeb 		   sizeof(regulatory->reg_6ghz_tpe)) != 0)
821*6d67aabdSBjoern A. Zeeb 		changed = true;
822*6d67aabdSBjoern A. Zeeb 
823*6d67aabdSBjoern A. Zeeb 	if (changed) {
824*6d67aabdSBjoern A. Zeeb 		if (new.valid)
825*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_REGD,
826*6d67aabdSBjoern A. Zeeb 				    "recalc 6 GHz reg TPE to %d dBm\n",
827*6d67aabdSBjoern A. Zeeb 				    new.constraint);
828*6d67aabdSBjoern A. Zeeb 		else
829*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_REGD,
830*6d67aabdSBjoern A. Zeeb 				    "recalc 6 GHz reg TPE to none\n");
831*6d67aabdSBjoern A. Zeeb 
832*6d67aabdSBjoern A. Zeeb 		regulatory->reg_6ghz_tpe = new;
833*6d67aabdSBjoern A. Zeeb 	}
834*6d67aabdSBjoern A. Zeeb 
835*6d67aabdSBjoern A. Zeeb 	return changed;
836*6d67aabdSBjoern A. Zeeb }
837*6d67aabdSBjoern A. Zeeb 
838*6d67aabdSBjoern A. Zeeb static int rtw89_reg_6ghz_tpe_recalc(struct rtw89_dev *rtwdev,
839*6d67aabdSBjoern A. Zeeb 				     struct rtw89_vif *rtwvif, bool active,
840*6d67aabdSBjoern A. Zeeb 				     unsigned int *changed)
841*6d67aabdSBjoern A. Zeeb {
842*6d67aabdSBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
843*6d67aabdSBjoern A. Zeeb 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
844*6d67aabdSBjoern A. Zeeb 	struct rtw89_reg_6ghz_tpe *tpe = &rtwvif->reg_6ghz_tpe;
845*6d67aabdSBjoern A. Zeeb 
846*6d67aabdSBjoern A. Zeeb 	memset(tpe, 0, sizeof(*tpe));
847*6d67aabdSBjoern A. Zeeb 
848*6d67aabdSBjoern A. Zeeb 	if (!active || rtwvif->reg_6ghz_power != RTW89_REG_6GHZ_POWER_STD)
849*6d67aabdSBjoern A. Zeeb 		goto bottom;
850*6d67aabdSBjoern A. Zeeb 
851*6d67aabdSBjoern A. Zeeb 	rtw89_calculate_tpe(rtwdev, tpe, &bss_conf->tpe);
852*6d67aabdSBjoern A. Zeeb 	if (!tpe->valid)
853*6d67aabdSBjoern A. Zeeb 		goto bottom;
854*6d67aabdSBjoern A. Zeeb 
855*6d67aabdSBjoern A. Zeeb 	if (tpe->constraint < RTW89_MIN_VALID_POWER_CONSTRAINT) {
856*6d67aabdSBjoern A. Zeeb 		rtw89_err(rtwdev,
857*6d67aabdSBjoern A. Zeeb 			  "%s: constraint %d dBm is less than min valid val\n",
858*6d67aabdSBjoern A. Zeeb 			  __func__, tpe->constraint);
859*6d67aabdSBjoern A. Zeeb 
860*6d67aabdSBjoern A. Zeeb 		tpe->valid = false;
861*6d67aabdSBjoern A. Zeeb 		return -EINVAL;
862*6d67aabdSBjoern A. Zeeb 	}
863*6d67aabdSBjoern A. Zeeb 
864*6d67aabdSBjoern A. Zeeb bottom:
865*6d67aabdSBjoern A. Zeeb 	*changed += __rtw89_reg_6ghz_tpe_recalc(rtwdev);
866*6d67aabdSBjoern A. Zeeb 	return 0;
867*6d67aabdSBjoern A. Zeeb }
868*6d67aabdSBjoern A. Zeeb 
869*6d67aabdSBjoern A. Zeeb static bool __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev)
870*6d67aabdSBjoern A. Zeeb {
871*6d67aabdSBjoern A. Zeeb 	struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory;
872*6d67aabdSBjoern A. Zeeb 	const struct rtw89_regd *regd = regulatory->regd;
873e2340276SBjoern A. Zeeb 	enum rtw89_reg_6ghz_power sel;
874e2340276SBjoern A. Zeeb 	const struct rtw89_chan *chan;
875e2340276SBjoern A. Zeeb 	struct rtw89_vif *rtwvif;
876e2340276SBjoern A. Zeeb 	int count = 0;
877*6d67aabdSBjoern A. Zeeb 	u8 index;
878e2340276SBjoern A. Zeeb 
879e2340276SBjoern A. Zeeb 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
880e2340276SBjoern A. Zeeb 		chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx);
881e2340276SBjoern A. Zeeb 		if (chan->band_type != RTW89_BAND_6G)
882e2340276SBjoern A. Zeeb 			continue;
883e2340276SBjoern A. Zeeb 
884e2340276SBjoern A. Zeeb 		if (count != 0 && rtwvif->reg_6ghz_power == sel)
885e2340276SBjoern A. Zeeb 			continue;
886e2340276SBjoern A. Zeeb 
887e2340276SBjoern A. Zeeb 		sel = rtwvif->reg_6ghz_power;
888e2340276SBjoern A. Zeeb 		count++;
889e2340276SBjoern A. Zeeb 	}
890e2340276SBjoern A. Zeeb 
891e2340276SBjoern A. Zeeb 	if (count != 1)
892e2340276SBjoern A. Zeeb 		sel = RTW89_REG_6GHZ_POWER_DFLT;
893e2340276SBjoern A. Zeeb 
894*6d67aabdSBjoern A. Zeeb 	if (sel == RTW89_REG_6GHZ_POWER_STD) {
895*6d67aabdSBjoern A. Zeeb 		index = rtw89_regd_get_index(regd);
896*6d67aabdSBjoern A. Zeeb 		if (index == RTW89_REGD_MAX_COUNTRY_NUM ||
897*6d67aabdSBjoern A. Zeeb 		    test_bit(index, regulatory->block_6ghz_sp)) {
898*6d67aabdSBjoern A. Zeeb 			rtw89_debug(rtwdev, RTW89_DBG_REGD,
899*6d67aabdSBjoern A. Zeeb 				    "%c%c 6 GHz SP is blocked by policy\n",
900*6d67aabdSBjoern A. Zeeb 				    regd->alpha2[0], regd->alpha2[1]);
901*6d67aabdSBjoern A. Zeeb 			sel = RTW89_REG_6GHZ_POWER_DFLT;
902*6d67aabdSBjoern A. Zeeb 		}
903*6d67aabdSBjoern A. Zeeb 	}
904*6d67aabdSBjoern A. Zeeb 
905e2340276SBjoern A. Zeeb 	if (regulatory->reg_6ghz_power == sel)
906*6d67aabdSBjoern A. Zeeb 		return false;
907e2340276SBjoern A. Zeeb 
908e2340276SBjoern A. Zeeb 	rtw89_debug(rtwdev, RTW89_DBG_REGD,
909e2340276SBjoern A. Zeeb 		    "recalc 6 GHz reg power type to %d\n", sel);
910e2340276SBjoern A. Zeeb 
911e2340276SBjoern A. Zeeb 	regulatory->reg_6ghz_power = sel;
912*6d67aabdSBjoern A. Zeeb 	return true;
913e2340276SBjoern A. Zeeb }
914e2340276SBjoern A. Zeeb 
915*6d67aabdSBjoern A. Zeeb static int rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev,
916*6d67aabdSBjoern A. Zeeb 				       struct rtw89_vif *rtwvif, bool active,
917*6d67aabdSBjoern A. Zeeb 				       unsigned int *changed)
918e2340276SBjoern A. Zeeb {
919e2340276SBjoern A. Zeeb 	struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
920e2340276SBjoern A. Zeeb 
921e2340276SBjoern A. Zeeb 	if (active) {
922e2340276SBjoern A. Zeeb 		switch (vif->bss_conf.power_type) {
923e2340276SBjoern A. Zeeb 		case IEEE80211_REG_VLP_AP:
924e2340276SBjoern A. Zeeb 			rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP;
925e2340276SBjoern A. Zeeb 			break;
926e2340276SBjoern A. Zeeb 		case IEEE80211_REG_LPI_AP:
927e2340276SBjoern A. Zeeb 			rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI;
928e2340276SBjoern A. Zeeb 			break;
929e2340276SBjoern A. Zeeb 		case IEEE80211_REG_SP_AP:
930e2340276SBjoern A. Zeeb 			rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD;
931e2340276SBjoern A. Zeeb 			break;
932e2340276SBjoern A. Zeeb 		default:
933e2340276SBjoern A. Zeeb 			rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
934e2340276SBjoern A. Zeeb 			break;
935e2340276SBjoern A. Zeeb 		}
936e2340276SBjoern A. Zeeb 	} else {
937e2340276SBjoern A. Zeeb 		rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT;
938e2340276SBjoern A. Zeeb 	}
939e2340276SBjoern A. Zeeb 
940*6d67aabdSBjoern A. Zeeb 	*changed += __rtw89_reg_6ghz_power_recalc(rtwdev);
941*6d67aabdSBjoern A. Zeeb 	return 0;
942*6d67aabdSBjoern A. Zeeb }
943*6d67aabdSBjoern A. Zeeb 
944*6d67aabdSBjoern A. Zeeb int rtw89_reg_6ghz_recalc(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
945*6d67aabdSBjoern A. Zeeb 			  bool active)
946*6d67aabdSBjoern A. Zeeb {
947*6d67aabdSBjoern A. Zeeb 	unsigned int changed = 0;
948*6d67aabdSBjoern A. Zeeb 	int ret;
949*6d67aabdSBjoern A. Zeeb 
950*6d67aabdSBjoern A. Zeeb 	lockdep_assert_held(&rtwdev->mutex);
951*6d67aabdSBjoern A. Zeeb 
952*6d67aabdSBjoern A. Zeeb 	/* The result of reg_6ghz_tpe may depend on reg_6ghz_power type,
953*6d67aabdSBjoern A. Zeeb 	 * so must do reg_6ghz_tpe_recalc() after reg_6ghz_power_recalc().
954*6d67aabdSBjoern A. Zeeb 	 */
955*6d67aabdSBjoern A. Zeeb 
956*6d67aabdSBjoern A. Zeeb 	ret = rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, active, &changed);
957*6d67aabdSBjoern A. Zeeb 	if (ret)
958*6d67aabdSBjoern A. Zeeb 		return ret;
959*6d67aabdSBjoern A. Zeeb 
960*6d67aabdSBjoern A. Zeeb 	ret = rtw89_reg_6ghz_tpe_recalc(rtwdev, rtwvif, active, &changed);
961*6d67aabdSBjoern A. Zeeb 	if (ret)
962*6d67aabdSBjoern A. Zeeb 		return ret;
963*6d67aabdSBjoern A. Zeeb 
964*6d67aabdSBjoern A. Zeeb 	if (changed)
965*6d67aabdSBjoern A. Zeeb 		rtw89_core_set_chip_txpwr(rtwdev);
966*6d67aabdSBjoern A. Zeeb 
967*6d67aabdSBjoern A. Zeeb 	return 0;
968e2340276SBjoern A. Zeeb }
969