1 | // SPDX-License-Identifier: ISC |
2 | /* Copyright (C) 2023 MediaTek Inc. */ |
3 | |
4 | #include <linux/etherdevice.h> |
5 | #include <linux/hwmon.h> |
6 | #include <linux/hwmon-sysfs.h> |
7 | #include <linux/thermal.h> |
8 | #include <linux/firmware.h> |
9 | #include "mt7925.h" |
10 | #include "mac.h" |
11 | #include "mcu.h" |
12 | |
13 | static ssize_t mt7925_thermal_temp_show(struct device *dev, |
14 | struct device_attribute *attr, |
15 | char *buf) |
16 | { |
17 | switch (to_sensor_dev_attr(attr)->index) { |
18 | case 0: { |
19 | struct mt792x_phy *phy = dev_get_drvdata(dev); |
20 | struct mt792x_dev *mdev = phy->dev; |
21 | int temperature; |
22 | |
23 | mt792x_mutex_acquire(mdev); |
24 | temperature = mt7925_mcu_get_temperature(phy); |
25 | mt792x_mutex_release(mdev); |
26 | |
27 | if (temperature < 0) |
28 | return temperature; |
29 | /* display in millidegree Celsius */ |
30 | return sprintf(buf, fmt: "%u\n" , temperature * 1000); |
31 | } |
32 | default: |
33 | return -EINVAL; |
34 | } |
35 | } |
36 | static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7925_thermal_temp, 0); |
37 | |
38 | static struct attribute *mt7925_hwmon_attrs[] = { |
39 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
40 | NULL, |
41 | }; |
42 | ATTRIBUTE_GROUPS(mt7925_hwmon); |
43 | |
44 | static int mt7925_thermal_init(struct mt792x_phy *phy) |
45 | { |
46 | struct wiphy *wiphy = phy->mt76->hw->wiphy; |
47 | struct device *hwmon; |
48 | const char *name; |
49 | |
50 | if (!IS_REACHABLE(CONFIG_HWMON)) |
51 | return 0; |
52 | |
53 | name = devm_kasprintf(dev: &wiphy->dev, GFP_KERNEL, fmt: "mt7925_%s" , |
54 | wiphy_name(wiphy)); |
55 | |
56 | hwmon = devm_hwmon_device_register_with_groups(dev: &wiphy->dev, name, drvdata: phy, |
57 | groups: mt7925_hwmon_groups); |
58 | return PTR_ERR_OR_ZERO(ptr: hwmon); |
59 | } |
60 | |
61 | void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2) |
62 | { |
63 | struct mt792x_phy *phy = &dev->phy; |
64 | struct mt7925_clc_rule_v2 *rule; |
65 | struct mt7925_clc *clc; |
66 | bool old = dev->has_eht, new = true; |
67 | u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(phy: &dev->phy, alpha2); |
68 | u8 *pos; |
69 | |
70 | if (mtcl_conf != MT792X_ACPI_MTCL_INVALID && |
71 | (((mtcl_conf >> 4) & 0x3) == 0)) { |
72 | new = false; |
73 | goto out; |
74 | } |
75 | |
76 | if (!phy->clc[MT792x_CLC_BE_CTRL]) |
77 | goto out; |
78 | |
79 | clc = (struct mt7925_clc *)phy->clc[MT792x_CLC_BE_CTRL]; |
80 | pos = clc->data; |
81 | |
82 | while (1) { |
83 | rule = (struct mt7925_clc_rule_v2 *)pos; |
84 | |
85 | if (rule->alpha2[0] == alpha2[0] && |
86 | rule->alpha2[1] == alpha2[1]) { |
87 | new = false; |
88 | break; |
89 | } |
90 | |
91 | /* Check the last one */ |
92 | if (rule->flag & BIT(0)) |
93 | break; |
94 | |
95 | pos += sizeof(*rule); |
96 | } |
97 | |
98 | out: |
99 | if (old == new) |
100 | return; |
101 | |
102 | dev->has_eht = new; |
103 | mt7925_set_stream_he_eht_caps(phy); |
104 | } |
105 | |
106 | static void |
107 | mt7925_regd_channel_update(struct wiphy *wiphy, struct mt792x_dev *dev) |
108 | { |
109 | #define IS_UNII_INVALID(idx, sfreq, efreq, cfreq) \ |
110 | (!(dev->phy.clc_chan_conf & BIT(idx)) && (cfreq) >= (sfreq) && (cfreq) <= (efreq)) |
111 | #define MT7925_UNII_59G_IS_VALID 0x1 |
112 | #define MT7925_UNII_6G_IS_VALID 0x1e |
113 | struct ieee80211_supported_band *sband; |
114 | struct mt76_dev *mdev = &dev->mt76; |
115 | struct ieee80211_channel *ch; |
116 | u32 mtcl_conf = mt792x_acpi_get_mtcl_conf(phy: &dev->phy, alpha2: mdev->alpha2); |
117 | int i; |
118 | |
119 | if (mtcl_conf != MT792X_ACPI_MTCL_INVALID) { |
120 | if ((mtcl_conf & 0x3) == 0) |
121 | dev->phy.clc_chan_conf &= ~MT7925_UNII_59G_IS_VALID; |
122 | if (((mtcl_conf >> 2) & 0x3) == 0) |
123 | dev->phy.clc_chan_conf &= ~MT7925_UNII_6G_IS_VALID; |
124 | } |
125 | |
126 | sband = wiphy->bands[NL80211_BAND_5GHZ]; |
127 | if (!sband) |
128 | return; |
129 | |
130 | for (i = 0; i < sband->n_channels; i++) { |
131 | ch = &sband->channels[i]; |
132 | |
133 | /* UNII-4 */ |
134 | if (IS_UNII_INVALID(0, 5845, 5925, ch->center_freq)) |
135 | ch->flags |= IEEE80211_CHAN_DISABLED; |
136 | } |
137 | |
138 | sband = wiphy->bands[NL80211_BAND_6GHZ]; |
139 | if (!sband) |
140 | return; |
141 | |
142 | for (i = 0; i < sband->n_channels; i++) { |
143 | ch = &sband->channels[i]; |
144 | |
145 | /* UNII-5/6/7/8 */ |
146 | if (IS_UNII_INVALID(1, 5925, 6425, ch->center_freq) || |
147 | IS_UNII_INVALID(2, 6425, 6525, ch->center_freq) || |
148 | IS_UNII_INVALID(3, 6525, 6875, ch->center_freq) || |
149 | IS_UNII_INVALID(4, 6875, 7125, ch->center_freq)) |
150 | ch->flags |= IEEE80211_CHAN_DISABLED; |
151 | } |
152 | } |
153 | |
154 | void mt7925_regd_update(struct mt792x_dev *dev) |
155 | { |
156 | struct mt76_dev *mdev = &dev->mt76; |
157 | struct ieee80211_hw *hw = mdev->hw; |
158 | struct wiphy *wiphy = hw->wiphy; |
159 | |
160 | if (!dev->regd_change) |
161 | return; |
162 | |
163 | mt7925_mcu_set_clc(dev, alpha2: mdev->alpha2, env_cap: dev->country_ie_env); |
164 | mt7925_regd_channel_update(wiphy, dev); |
165 | mt7925_mcu_set_channel_domain(phy: hw->priv); |
166 | mt7925_set_tx_sar_pwr(hw, NULL); |
167 | dev->regd_change = false; |
168 | } |
169 | EXPORT_SYMBOL_GPL(mt7925_regd_update); |
170 | |
171 | static void |
172 | mt7925_regd_notifier(struct wiphy *wiphy, |
173 | struct regulatory_request *req) |
174 | { |
175 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
176 | struct mt792x_dev *dev = mt792x_hw_dev(hw); |
177 | struct mt76_dev *mdev = &dev->mt76; |
178 | struct mt76_connac_pm *pm = &dev->pm; |
179 | |
180 | /* allow world regdom at the first boot only */ |
181 | if (!memcmp(p: req->alpha2, q: "00" , size: 2) && |
182 | mdev->alpha2[0] && mdev->alpha2[1]) |
183 | return; |
184 | |
185 | /* do not need to update the same country twice */ |
186 | if (!memcmp(p: req->alpha2, q: mdev->alpha2, size: 2) && |
187 | dev->country_ie_env == req->country_ie_env) |
188 | return; |
189 | |
190 | memcpy(mdev->alpha2, req->alpha2, 2); |
191 | mdev->region = req->dfs_region; |
192 | dev->country_ie_env = req->country_ie_env; |
193 | dev->regd_change = true; |
194 | |
195 | if (pm->suspended) |
196 | return; |
197 | |
198 | dev->regd_in_progress = true; |
199 | mt792x_mutex_acquire(dev); |
200 | mt7925_regd_update(dev); |
201 | mt792x_mutex_release(dev); |
202 | dev->regd_in_progress = false; |
203 | wake_up(&dev->wait); |
204 | } |
205 | |
206 | static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev) |
207 | { |
208 | int i; |
209 | |
210 | for (i = 0; i < ARRAY_SIZE(mt76_rates); i++) { |
211 | u16 rate = mt76_rates[i].hw_value; |
212 | u16 idx = MT792x_BASIC_RATES_TBL + i; |
213 | |
214 | rate = FIELD_PREP(MT_TX_RATE_MODE, rate >> 8) | |
215 | FIELD_PREP(MT_TX_RATE_IDX, rate & GENMASK(7, 0)); |
216 | mt7925_mac_set_fixed_rate_table(dev, tbl_idx: idx, rate_idx: rate); |
217 | } |
218 | } |
219 | |
220 | int mt7925_mac_init(struct mt792x_dev *dev) |
221 | { |
222 | int i; |
223 | |
224 | mt76_rmw_field(dev, MT_MDP_DCR1, MT_MDP_DCR1_MAX_RX_LEN, 1536); |
225 | /* enable hardware de-agg */ |
226 | mt76_set(dev, MT_MDP_DCR0, MT_MDP_DCR0_DAMSDU_EN); |
227 | |
228 | for (i = 0; i < MT792x_WTBL_SIZE; i++) |
229 | mt7925_mac_wtbl_update(dev, idx: i, |
230 | MT_WTBL_UPDATE_ADM_COUNT_CLEAR); |
231 | for (i = 0; i < 2; i++) |
232 | mt792x_mac_init_band(dev, band: i); |
233 | |
234 | mt7925_mac_init_basic_rates(dev); |
235 | |
236 | memzero_explicit(s: &dev->mt76.alpha2, count: sizeof(dev->mt76.alpha2)); |
237 | |
238 | return 0; |
239 | } |
240 | EXPORT_SYMBOL_GPL(mt7925_mac_init); |
241 | |
242 | static int __mt7925_init_hardware(struct mt792x_dev *dev) |
243 | { |
244 | int ret; |
245 | |
246 | ret = mt792x_mcu_init(dev); |
247 | if (ret) |
248 | goto out; |
249 | |
250 | mt76_eeprom_override(phy: &dev->mphy); |
251 | |
252 | ret = mt7925_mcu_set_eeprom(dev); |
253 | if (ret) |
254 | goto out; |
255 | |
256 | ret = mt7925_mac_init(dev); |
257 | if (ret) |
258 | goto out; |
259 | |
260 | out: |
261 | return ret; |
262 | } |
263 | |
264 | static int mt7925_init_hardware(struct mt792x_dev *dev) |
265 | { |
266 | int ret, i; |
267 | |
268 | set_bit(nr: MT76_STATE_INITIALIZED, addr: &dev->mphy.state); |
269 | |
270 | for (i = 0; i < MT792x_MCU_INIT_RETRY_COUNT; i++) { |
271 | ret = __mt7925_init_hardware(dev); |
272 | if (!ret) |
273 | break; |
274 | |
275 | mt792x_init_reset(dev); |
276 | } |
277 | |
278 | if (i == MT792x_MCU_INIT_RETRY_COUNT) { |
279 | dev_err(dev->mt76.dev, "hardware init failed\n" ); |
280 | return ret; |
281 | } |
282 | |
283 | return 0; |
284 | } |
285 | |
286 | static void mt7925_init_work(struct work_struct *work) |
287 | { |
288 | struct mt792x_dev *dev = container_of(work, struct mt792x_dev, |
289 | init_work); |
290 | int ret; |
291 | |
292 | ret = mt7925_init_hardware(dev); |
293 | if (ret) |
294 | return; |
295 | |
296 | mt76_set_stream_caps(phy: &dev->mphy, vht: true); |
297 | mt7925_set_stream_he_eht_caps(phy: &dev->phy); |
298 | mt792x_config_mac_addr_list(dev); |
299 | |
300 | ret = mt7925_init_mlo_caps(phy: &dev->phy); |
301 | if (ret) { |
302 | dev_err(dev->mt76.dev, "MLO init failed\n" ); |
303 | return; |
304 | } |
305 | |
306 | ret = mt76_register_device(dev: &dev->mt76, vht: true, rates: mt76_rates, |
307 | ARRAY_SIZE(mt76_rates)); |
308 | if (ret) { |
309 | dev_err(dev->mt76.dev, "register device failed\n" ); |
310 | return; |
311 | } |
312 | |
313 | ret = mt7925_init_debugfs(dev); |
314 | if (ret) { |
315 | dev_err(dev->mt76.dev, "register debugfs failed\n" ); |
316 | return; |
317 | } |
318 | |
319 | ret = mt7925_thermal_init(phy: &dev->phy); |
320 | if (ret) { |
321 | dev_err(dev->mt76.dev, "thermal init failed\n" ); |
322 | return; |
323 | } |
324 | |
325 | ret = mt7925_mcu_set_thermal_protect(dev); |
326 | if (ret) { |
327 | dev_err(dev->mt76.dev, "thermal protection enable failed\n" ); |
328 | return; |
329 | } |
330 | |
331 | /* we support chip reset now */ |
332 | dev->hw_init_done = true; |
333 | |
334 | mt7925_mcu_set_deep_sleep(dev, enable: dev->pm.ds_enable); |
335 | } |
336 | |
337 | int mt7925_register_device(struct mt792x_dev *dev) |
338 | { |
339 | struct ieee80211_hw *hw = mt76_hw(dev); |
340 | int ret; |
341 | |
342 | dev->phy.dev = dev; |
343 | dev->phy.mt76 = &dev->mt76.phy; |
344 | dev->mt76.phy.priv = &dev->phy; |
345 | dev->mt76.tx_worker.fn = mt792x_tx_worker; |
346 | |
347 | INIT_DELAYED_WORK(&dev->pm.ps_work, mt792x_pm_power_save_work); |
348 | INIT_DELAYED_WORK(&dev->mlo_pm_work, mt7925_mlo_pm_work); |
349 | INIT_WORK(&dev->pm.wake_work, mt792x_pm_wake_work); |
350 | spin_lock_init(&dev->pm.wake.lock); |
351 | mutex_init(&dev->pm.mutex); |
352 | init_waitqueue_head(&dev->pm.wait); |
353 | init_waitqueue_head(&dev->wait); |
354 | spin_lock_init(&dev->pm.txq_lock); |
355 | INIT_DELAYED_WORK(&dev->mphy.mac_work, mt792x_mac_work); |
356 | INIT_DELAYED_WORK(&dev->phy.scan_work, mt7925_scan_work); |
357 | INIT_DELAYED_WORK(&dev->coredump.work, mt7925_coredump_work); |
358 | #if IS_ENABLED(CONFIG_IPV6) |
359 | INIT_WORK(&dev->ipv6_ns_work, mt7925_set_ipv6_ns_work); |
360 | skb_queue_head_init(list: &dev->ipv6_ns_list); |
361 | #endif |
362 | skb_queue_head_init(list: &dev->phy.scan_event_list); |
363 | skb_queue_head_init(list: &dev->coredump.msg_list); |
364 | |
365 | INIT_WORK(&dev->reset_work, mt7925_mac_reset_work); |
366 | INIT_WORK(&dev->init_work, mt7925_init_work); |
367 | |
368 | INIT_WORK(&dev->phy.roc_work, mt7925_roc_work); |
369 | timer_setup(&dev->phy.roc_timer, mt792x_roc_timer, 0); |
370 | init_waitqueue_head(&dev->phy.roc_wait); |
371 | |
372 | dev->pm.idle_timeout = MT792x_PM_TIMEOUT; |
373 | dev->pm.stats.last_wake_event = jiffies; |
374 | dev->pm.stats.last_doze_event = jiffies; |
375 | if (!mt76_is_usb(&dev->mt76)) { |
376 | dev->pm.enable_user = true; |
377 | dev->pm.enable = true; |
378 | dev->pm.ds_enable_user = true; |
379 | dev->pm.ds_enable = true; |
380 | } |
381 | |
382 | if (!mt76_is_mmio(&dev->mt76)) |
383 | hw->extra_tx_headroom += MT_SDIO_TXD_SIZE + MT_SDIO_HDR_SIZE; |
384 | |
385 | mt792x_init_acpi_sar(dev); |
386 | |
387 | ret = mt792x_init_wcid(dev); |
388 | if (ret) |
389 | return ret; |
390 | |
391 | ret = mt792x_init_wiphy(hw); |
392 | if (ret) |
393 | return ret; |
394 | |
395 | hw->wiphy->reg_notifier = mt7925_regd_notifier; |
396 | dev->mphy.sband_2g.sband.ht_cap.cap |= |
397 | IEEE80211_HT_CAP_LDPC_CODING | |
398 | IEEE80211_HT_CAP_MAX_AMSDU; |
399 | dev->mphy.sband_2g.sband.ht_cap.ampdu_density = |
400 | IEEE80211_HT_MPDU_DENSITY_2; |
401 | dev->mphy.sband_5g.sband.ht_cap.cap |= |
402 | IEEE80211_HT_CAP_LDPC_CODING | |
403 | IEEE80211_HT_CAP_MAX_AMSDU; |
404 | dev->mphy.sband_2g.sband.ht_cap.ampdu_density = |
405 | IEEE80211_HT_MPDU_DENSITY_1; |
406 | dev->mphy.sband_5g.sband.vht_cap.cap |= |
407 | IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | |
408 | IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK | |
409 | IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE | |
410 | IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | |
411 | (3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT); |
412 | dev->mphy.sband_5g.sband.vht_cap.cap |= |
413 | IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | |
414 | IEEE80211_VHT_CAP_SHORT_GI_160; |
415 | |
416 | dev->mphy.hw->wiphy->available_antennas_rx = dev->mphy.chainmask; |
417 | dev->mphy.hw->wiphy->available_antennas_tx = dev->mphy.chainmask; |
418 | |
419 | queue_work(wq: system_wq, work: &dev->init_work); |
420 | |
421 | return 0; |
422 | } |
423 | EXPORT_SYMBOL_GPL(mt7925_register_device); |
424 | |