1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2022 MediaTek Inc. */
3 
4 #include <linux/acpi.h>
5 #include "mt7921.h"
6 
7 static int
mt7921_acpi_read(struct mt7921_dev * dev,u8 * method,u8 ** tbl,u32 * len)8 mt7921_acpi_read(struct mt7921_dev *dev, u8 *method, u8 **tbl, u32 *len)
9 {
10 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
11 	union acpi_object *sar_root, *sar_unit;
12 	struct mt76_dev *mdev = &dev->mt76;
13 	acpi_handle root, handle;
14 	acpi_status status;
15 	u32 i = 0;
16 	int ret;
17 
18 	root = ACPI_HANDLE(mdev->dev);
19 	if (!root)
20 		return -EOPNOTSUPP;
21 
22 	status = acpi_get_handle(root, method, &handle);
23 	if (ACPI_FAILURE(status))
24 		return -EIO;
25 
26 	status = acpi_evaluate_object(handle, NULL, NULL, &buf);
27 	if (ACPI_FAILURE(status))
28 		return -EIO;
29 
30 	sar_root = buf.pointer;
31 	if (sar_root->type != ACPI_TYPE_PACKAGE ||
32 	    sar_root->package.count < 4 ||
33 	    sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
34 		dev_err(mdev->dev, "sar cnt = %d\n",
35 			sar_root->package.count);
36 		ret = -EINVAL;
37 		goto free;
38 	}
39 
40 	if (!*tbl) {
41 		*tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
42 				    GFP_KERNEL);
43 		if (!*tbl) {
44 			ret = -ENOMEM;
45 			goto free;
46 		}
47 	}
48 	if (len)
49 		*len = sar_root->package.count;
50 
51 	for (i = 0; i < sar_root->package.count; i++) {
52 		sar_unit = &sar_root->package.elements[i];
53 
54 		if (sar_unit->type != ACPI_TYPE_INTEGER)
55 			break;
56 		*(*tbl + i) = (u8)sar_unit->integer.value;
57 	}
58 	ret = (i == sar_root->package.count) ? 0 : -EINVAL;
59 
60 free:
61 	kfree(sar_root);
62 
63 	return ret;
64 }
65 
66 /* MTCL : Country List Table for 6G band */
67 static int
mt7921_asar_acpi_read_mtcl(struct mt7921_dev * dev,u8 ** table,u8 * version)68 mt7921_asar_acpi_read_mtcl(struct mt7921_dev *dev, u8 **table, u8 *version)
69 {
70 	*version = (mt7921_acpi_read(dev, MT7921_ACPI_MTCL, table, NULL) < 0)
71 		   ? 1 : 2;
72 	return 0;
73 }
74 
75 /* MTDS : Dynamic SAR Power Table */
76 static int
mt7921_asar_acpi_read_mtds(struct mt7921_dev * dev,u8 ** table,u8 version)77 mt7921_asar_acpi_read_mtds(struct mt7921_dev *dev, u8 **table, u8 version)
78 {
79 	int len, ret, sarlen, prelen, tblcnt;
80 	bool enable;
81 
82 	ret = mt7921_acpi_read(dev, MT7921_ACPI_MTDS, table, &len);
83 	if (ret)
84 		return ret;
85 
86 	/* Table content validation */
87 	switch (version) {
88 	case 1:
89 		enable = ((struct mt7921_asar_dyn *)*table)->enable;
90 		sarlen = sizeof(struct mt7921_asar_dyn_limit);
91 		prelen = sizeof(struct mt7921_asar_dyn);
92 		break;
93 	case 2:
94 		enable = ((struct mt7921_asar_dyn_v2 *)*table)->enable;
95 		sarlen = sizeof(struct mt7921_asar_dyn_limit_v2);
96 		prelen = sizeof(struct mt7921_asar_dyn_v2);
97 		break;
98 	default:
99 		return -EINVAL;
100 	}
101 
102 	tblcnt = (len - prelen) / sarlen;
103 	if (!enable ||
104 	    tblcnt > MT7921_ASAR_MAX_DYN || tblcnt < MT7921_ASAR_MIN_DYN)
105 		ret = -EINVAL;
106 
107 	return ret;
108 }
109 
110 /* MTGS : Geo SAR Power Table */
111 static int
mt7921_asar_acpi_read_mtgs(struct mt7921_dev * dev,u8 ** table,u8 version)112 mt7921_asar_acpi_read_mtgs(struct mt7921_dev *dev, u8 **table, u8 version)
113 {
114 	int len, ret = 0, sarlen, prelen, tblcnt;
115 
116 	ret = mt7921_acpi_read(dev, MT7921_ACPI_MTGS, table, &len);
117 	if (ret)
118 		return ret;
119 
120 	/* Table content validation */
121 	switch (version) {
122 	case 1:
123 		sarlen = sizeof(struct mt7921_asar_geo_limit);
124 		prelen = sizeof(struct mt7921_asar_geo);
125 		break;
126 	case 2:
127 		sarlen = sizeof(struct mt7921_asar_geo_limit_v2);
128 		prelen = sizeof(struct mt7921_asar_geo_v2);
129 		break;
130 	default:
131 		return -EINVAL;
132 	}
133 
134 	tblcnt = (len - prelen) / sarlen;
135 	if (tblcnt > MT7921_ASAR_MAX_GEO || tblcnt < MT7921_ASAR_MIN_GEO)
136 		ret = -EINVAL;
137 
138 	return ret;
139 }
140 
141 /* MTFG : Flag Table */
142 static int
mt7921_asar_acpi_read_mtfg(struct mt7921_dev * dev,u8 ** table)143 mt7921_asar_acpi_read_mtfg(struct mt7921_dev *dev, u8 **table)
144 {
145 	int len, ret;
146 
147 	ret = mt7921_acpi_read(dev, MT7921_ACPI_MTFG, table, &len);
148 	if (ret)
149 		return ret;
150 
151 	if (len < MT7921_ASAR_MIN_FG)
152 		ret = -EINVAL;
153 
154 	return ret;
155 }
156 
mt7921_init_acpi_sar(struct mt7921_dev * dev)157 int mt7921_init_acpi_sar(struct mt7921_dev *dev)
158 {
159 	struct mt7921_acpi_sar *asar;
160 	int ret;
161 
162 	asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
163 	if (!asar)
164 		return -ENOMEM;
165 
166 	mt7921_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
167 
168 	/* MTDS is mandatory. Return error if table is invalid */
169 	ret = mt7921_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
170 	if (ret) {
171 		devm_kfree(dev->mt76.dev, asar->dyn);
172 		devm_kfree(dev->mt76.dev, asar->countrylist);
173 		devm_kfree(dev->mt76.dev, asar);
174 		return ret;
175 	}
176 
177 	/* MTGS is optional */
178 	ret = mt7921_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
179 	if (ret) {
180 		devm_kfree(dev->mt76.dev, asar->geo);
181 		asar->geo = NULL;
182 	}
183 
184 	/* MTFG is optional */
185 	ret = mt7921_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
186 	if (ret) {
187 		devm_kfree(dev->mt76.dev, asar->fg);
188 		asar->fg = NULL;
189 	}
190 	dev->phy.acpisar = asar;
191 
192 	return 0;
193 }
194 
195 static s8
mt7921_asar_get_geo_pwr(struct mt7921_phy * phy,enum nl80211_band band,s8 dyn_power)196 mt7921_asar_get_geo_pwr(struct mt7921_phy *phy,
197 			enum nl80211_band band, s8 dyn_power)
198 {
199 	struct mt7921_acpi_sar *asar = phy->acpisar;
200 	struct mt7921_asar_geo_band *band_pwr;
201 	s8 geo_power;
202 	u8 idx, max;
203 
204 	if (!asar->geo)
205 		return dyn_power;
206 
207 	switch (phy->mt76->dev->region) {
208 	case NL80211_DFS_FCC:
209 		idx = 0;
210 		break;
211 	case NL80211_DFS_ETSI:
212 		idx = 1;
213 		break;
214 	default: /* WW */
215 		idx = 2;
216 		break;
217 	}
218 
219 	if (asar->ver == 1) {
220 		band_pwr = &asar->geo->tbl[idx].band[0];
221 		max = ARRAY_SIZE(asar->geo->tbl[idx].band);
222 	} else {
223 		band_pwr = &asar->geo_v2->tbl[idx].band[0];
224 		max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
225 	}
226 
227 	switch (band) {
228 	case NL80211_BAND_2GHZ:
229 		idx = 0;
230 		break;
231 	case NL80211_BAND_5GHZ:
232 		idx = 1;
233 		break;
234 	case NL80211_BAND_6GHZ:
235 		idx = 2;
236 		break;
237 	default:
238 		return dyn_power;
239 	}
240 
241 	if (idx >= max)
242 		return dyn_power;
243 
244 	geo_power = (band_pwr + idx)->pwr;
245 	dyn_power += (band_pwr + idx)->offset;
246 
247 	return min(geo_power, dyn_power);
248 }
249 
250 static s8
mt7921_asar_range_pwr(struct mt7921_phy * phy,const struct cfg80211_sar_freq_ranges * range,u8 idx)251 mt7921_asar_range_pwr(struct mt7921_phy *phy,
252 		      const struct cfg80211_sar_freq_ranges *range,
253 		      u8 idx)
254 {
255 	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
256 	struct mt7921_acpi_sar *asar = phy->acpisar;
257 	u8 *limit, band, max;
258 
259 	if (!capa)
260 		return 127;
261 
262 	if (asar->ver == 1) {
263 		limit = &asar->dyn->tbl[0].frp[0];
264 		max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
265 	} else {
266 		limit = &asar->dyn_v2->tbl[0].frp[0];
267 		max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
268 	}
269 
270 	if (idx >= max)
271 		return 127;
272 
273 	if (range->start_freq >= 5945)
274 		band = NL80211_BAND_6GHZ;
275 	else if (range->start_freq >= 5150)
276 		band = NL80211_BAND_5GHZ;
277 	else
278 		band = NL80211_BAND_2GHZ;
279 
280 	return mt7921_asar_get_geo_pwr(phy, band, limit[idx]);
281 }
282 
mt7921_init_acpi_sar_power(struct mt7921_phy * phy,bool set_default)283 int mt7921_init_acpi_sar_power(struct mt7921_phy *phy, bool set_default)
284 {
285 	const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
286 	int i;
287 
288 	if (!phy->acpisar)
289 		return 0;
290 
291 	/* When ACPI SAR enabled in HW, we should apply rules for .frp
292 	 * 1. w/o .sar_specs : set ACPI SAR power as the defatul value
293 	 * 2. w/  .sar_specs : set power with min(.sar_specs, ACPI_SAR)
294 	 */
295 	for (i = 0; i < capa->num_freq_ranges; i++) {
296 		struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
297 
298 		frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
299 		if (!frp->range)
300 			continue;
301 
302 		frp->power = min_t(s8, set_default ? 127 : frp->power,
303 				   mt7921_asar_range_pwr(phy, frp->range, i));
304 	}
305 
306 	return 0;
307 }
308 
mt7921_acpi_get_flags(struct mt7921_phy * phy)309 u8 mt7921_acpi_get_flags(struct mt7921_phy *phy)
310 {
311 	struct mt7921_asar_fg *fg;
312 	struct {
313 		u8 acpi_idx;
314 		u8 chip_idx;
315 	} map[] = {
316 		{1, 1},
317 		{4, 2},
318 	};
319 	u8 flags = BIT(0);
320 	int i, j;
321 
322 	if (!phy->acpisar)
323 		return 0;
324 
325 	fg = phy->acpisar->fg;
326 	if (!fg)
327 		return flags;
328 
329 	/* pickup necessary settings per device and
330 	 * translate the index of bitmap for chip command.
331 	 */
332 	for (i = 0; i < fg->nr_flag; i++)
333 		for (j = 0; j < ARRAY_SIZE(map); j++)
334 			if (fg->flag[i] == map[j].acpi_idx) {
335 				flags |= BIT(map[j].chip_idx);
336 				break;
337 			}
338 
339 	return flags;
340 }
341