2 * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
3 * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
4 * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/module.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/mtd/partitions.h>
20 #include <linux/etherdevice.h>
21 #include <asm/unaligned.h>
24 #include "../mt76x02_phy.h"
26 #define MT_MAP_READS DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16)
28 mt76x0_efuse_physical_size_check(struct mt76x02_dev
*dev
)
30 u8 data
[MT_MAP_READS
* 16];
32 u32 start
= 0, end
= 0, cnt_free
;
34 ret
= mt76x02_get_efuse_data(dev
, MT_EE_USAGE_MAP_START
, data
,
35 sizeof(data
), MT_EE_PHYSICAL_READ
);
39 for (i
= 0; i
< MT_EFUSE_USAGE_MAP_SIZE
; i
++)
42 start
= MT_EE_USAGE_MAP_START
+ i
;
43 end
= MT_EE_USAGE_MAP_START
+ i
;
45 cnt_free
= end
- start
+ 1;
47 if (MT_EFUSE_USAGE_MAP_SIZE
- cnt_free
< 5) {
48 dev_err(dev
->mt76
.dev
,
49 "driver does not support default EEPROM\n");
56 static void mt76x0_set_chip_cap(struct mt76x02_dev
*dev
)
58 u16 nic_conf0
= mt76x02_eeprom_get(dev
, MT_EE_NIC_CONF_0
);
59 u16 nic_conf1
= mt76x02_eeprom_get(dev
, MT_EE_NIC_CONF_1
);
61 mt76x02_eeprom_parse_hw_cap(dev
);
62 dev_dbg(dev
->mt76
.dev
, "2GHz %d 5GHz %d\n",
63 dev
->mt76
.cap
.has_2ghz
, dev
->mt76
.cap
.has_5ghz
);
66 dev
->mt76
.cap
.has_2ghz
= false;
67 dev_dbg(dev
->mt76
.dev
, "mask out 2GHz support\n");
70 if (!mt76x02_field_valid(nic_conf1
& 0xff))
73 if (nic_conf1
& MT_EE_NIC_CONF_1_HW_RF_CTRL
)
74 dev_err(dev
->mt76
.dev
,
75 "driver does not support HW RF ctrl\n");
77 if (!mt76x02_field_valid(nic_conf0
>> 8))
80 if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH
, nic_conf0
) > 1 ||
81 FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH
, nic_conf0
) > 1)
82 dev_err(dev
->mt76
.dev
, "invalid tx-rx stream\n");
85 static void mt76x0_set_temp_offset(struct mt76x02_dev
*dev
)
89 val
= mt76x02_eeprom_get(dev
, MT_EE_2G_TARGET_POWER
) >> 8;
90 if (mt76x02_field_valid(val
))
91 dev
->cal
.rx
.temp_offset
= mt76x02_sign_extend(val
, 8);
93 dev
->cal
.rx
.temp_offset
= -10;
96 static void mt76x0_set_freq_offset(struct mt76x02_dev
*dev
)
98 struct mt76x02_rx_freq_cal
*caldata
= &dev
->cal
.rx
;
101 val
= mt76x02_eeprom_get(dev
, MT_EE_FREQ_OFFSET
);
102 if (!mt76x02_field_valid(val
))
104 caldata
->freq_offset
= val
;
106 val
= mt76x02_eeprom_get(dev
, MT_EE_TSSI_BOUND4
) >> 8;
107 if (!mt76x02_field_valid(val
))
110 caldata
->freq_offset
-= mt76x02_sign_extend(val
, 8);
113 void mt76x0_read_rx_gain(struct mt76x02_dev
*dev
)
115 struct ieee80211_channel
*chan
= dev
->mt76
.chandef
.chan
;
116 struct mt76x02_rx_freq_cal
*caldata
= &dev
->cal
.rx
;
117 s8 val
, lna_5g
[3], lna_2g
;
121 mt76x02_get_rx_gain(dev
, chan
->band
, &rssi_offset
, &lna_2g
, lna_5g
);
122 caldata
->lna_gain
= mt76x02_get_lna_gain(dev
, &lna_2g
, lna_5g
, chan
);
124 for (i
= 0; i
< ARRAY_SIZE(caldata
->rssi_offset
); i
++) {
125 val
= rssi_offset
>> (8 * i
);
126 if (val
< -10 || val
> 10)
129 caldata
->rssi_offset
[i
] = val
;
133 static s8
mt76x0_get_delta(struct mt76x02_dev
*dev
)
135 struct cfg80211_chan_def
*chandef
= &dev
->mt76
.chandef
;
138 if (chandef
->width
== NL80211_CHAN_WIDTH_80
) {
139 val
= mt76x02_eeprom_get(dev
, MT_EE_5G_TARGET_POWER
) >> 8;
140 } else if (chandef
->width
== NL80211_CHAN_WIDTH_40
) {
143 data
= mt76x02_eeprom_get(dev
, MT_EE_TX_POWER_DELTA_BW40
);
144 if (chandef
->chan
->band
== NL80211_BAND_5GHZ
)
152 return mt76x02_rate_power_val(val
);
155 void mt76x0_get_tx_power_per_rate(struct mt76x02_dev
*dev
)
157 struct ieee80211_channel
*chan
= dev
->mt76
.chandef
.chan
;
158 bool is_2ghz
= chan
->band
== NL80211_BAND_2GHZ
;
159 struct mt76_rate_power
*t
= &dev
->mt76
.rate_power
;
163 memset(t
, 0, sizeof(*t
));
165 /* cck 1M, 2M, 5.5M, 11M */
166 val
= mt76x02_eeprom_get(dev
, MT_EE_TX_POWER_BYRATE_BASE
);
167 t
->cck
[0] = t
->cck
[1] = s6_to_s8(val
);
168 t
->cck
[2] = t
->cck
[3] = s6_to_s8(val
>> 8);
170 /* ofdm 6M, 9M, 12M, 18M */
171 addr
= is_2ghz
? MT_EE_TX_POWER_BYRATE_BASE
+ 2 : 0x120;
172 val
= mt76x02_eeprom_get(dev
, addr
);
173 t
->ofdm
[0] = t
->ofdm
[1] = s6_to_s8(val
);
174 t
->ofdm
[2] = t
->ofdm
[3] = s6_to_s8(val
>> 8);
176 /* ofdm 24M, 36M, 48M, 54M */
177 addr
= is_2ghz
? MT_EE_TX_POWER_BYRATE_BASE
+ 4 : 0x122;
178 val
= mt76x02_eeprom_get(dev
, addr
);
179 t
->ofdm
[4] = t
->ofdm
[5] = s6_to_s8(val
);
180 t
->ofdm
[6] = t
->ofdm
[7] = s6_to_s8(val
>> 8);
182 /* ht-vht mcs 1ss 0, 1, 2, 3 */
183 addr
= is_2ghz
? MT_EE_TX_POWER_BYRATE_BASE
+ 6 : 0x124;
184 val
= mt76x02_eeprom_get(dev
, addr
);
185 t
->ht
[0] = t
->ht
[1] = t
->vht
[0] = t
->vht
[1] = s6_to_s8(val
);
186 t
->ht
[2] = t
->ht
[3] = t
->vht
[2] = t
->vht
[3] = s6_to_s8(val
>> 8);
188 /* ht-vht mcs 1ss 4, 5, 6 */
189 addr
= is_2ghz
? MT_EE_TX_POWER_BYRATE_BASE
+ 8 : 0x126;
190 val
= mt76x02_eeprom_get(dev
, addr
);
191 t
->ht
[4] = t
->ht
[5] = t
->vht
[4] = t
->vht
[5] = s6_to_s8(val
);
192 t
->ht
[6] = t
->vht
[6] = s6_to_s8(val
>> 8);
194 /* ht-vht mcs 1ss 0, 1, 2, 3 stbc */
195 addr
= is_2ghz
? MT_EE_TX_POWER_BYRATE_BASE
+ 14 : 0xec;
196 val
= mt76x02_eeprom_get(dev
, addr
);
197 t
->stbc
[0] = t
->stbc
[1] = s6_to_s8(val
);
198 t
->stbc
[2] = t
->stbc
[3] = s6_to_s8(val
>> 8);
200 /* ht-vht mcs 1ss 4, 5, 6 stbc */
201 addr
= is_2ghz
? MT_EE_TX_POWER_BYRATE_BASE
+ 16 : 0xee;
202 val
= mt76x02_eeprom_get(dev
, addr
);
203 t
->stbc
[4] = t
->stbc
[5] = s6_to_s8(val
);
204 t
->stbc
[6] = t
->stbc
[7] = s6_to_s8(val
>> 8);
206 /* vht mcs 8, 9 5GHz */
207 val
= mt76x02_eeprom_get(dev
, 0x132);
208 t
->vht
[7] = s6_to_s8(val
);
209 t
->vht
[8] = s6_to_s8(val
>> 8);
211 delta
= mt76x0_tssi_enabled(dev
) ? 0 : mt76x0_get_delta(dev
);
212 mt76x02_add_rate_power_offset(t
, delta
);
215 void mt76x0_get_power_info(struct mt76x02_dev
*dev
, s8
*tp
)
217 struct mt76x0_chan_map
{
221 { 2, 0 }, { 4, 2 }, { 6, 4 }, { 8, 6 },
222 { 10, 8 }, { 12, 10 }, { 14, 12 }, { 38, 0 },
223 { 44, 2 }, { 48, 4 }, { 54, 6 }, { 60, 8 },
224 { 64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 },
225 { 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 },
226 { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
227 { 167, 34 }, { 171, 36 }, { 175, 38 },
229 struct ieee80211_channel
*chan
= dev
->mt76
.chandef
.chan
;
234 if (mt76x0_tssi_enabled(dev
)) {
237 if (chan
->band
== NL80211_BAND_5GHZ
)
238 data
= mt76x02_eeprom_get(dev
, MT_EE_5G_TARGET_POWER
);
240 data
= mt76x02_eeprom_get(dev
, MT_EE_2G_TARGET_POWER
);
241 target_power
= (data
& 0xff) - dev
->mt76
.rate_power
.ofdm
[7];
242 *tp
= target_power
+ mt76x0_get_delta(dev
);
247 for (i
= 0; i
< ARRAY_SIZE(chan_map
); i
++) {
248 if (chan
->hw_value
<= chan_map
[i
].chan
) {
249 idx
= (chan
->hw_value
== chan_map
[i
].chan
);
250 offset
= chan_map
[i
].offset
;
254 if (i
== ARRAY_SIZE(chan_map
))
255 offset
= chan_map
[0].offset
;
257 if (chan
->band
== NL80211_BAND_2GHZ
) {
258 addr
= MT_EE_TX_POWER_DELTA_BW80
+ offset
;
260 switch (chan
->hw_value
) {
279 addr
= MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE
+ 2 + offset
;
282 data
= mt76x02_eeprom_get(dev
, addr
);
283 *tp
= data
>> (8 * idx
);
284 if (*tp
< 0 || *tp
> 0x3f)
288 static int mt76x0_check_eeprom(struct mt76x02_dev
*dev
)
292 val
= get_unaligned_le16(dev
->mt76
.eeprom
.data
);
294 val
= get_unaligned_le16(dev
->mt76
.eeprom
.data
+
302 dev_err(dev
->mt76
.dev
, "EEPROM data check failed: %04x\n",
308 static int mt76x0_load_eeprom(struct mt76x02_dev
*dev
)
312 found
= mt76_eeprom_init(&dev
->mt76
, MT76X0_EEPROM_SIZE
);
316 if (found
&& !mt76x0_check_eeprom(dev
))
319 found
= mt76x0_efuse_physical_size_check(dev
);
323 return mt76x02_get_efuse_data(dev
, 0, dev
->mt76
.eeprom
.data
,
324 MT76X0_EEPROM_SIZE
, MT_EE_READ
);
327 int mt76x0_eeprom_init(struct mt76x02_dev
*dev
)
333 err
= mt76x0_load_eeprom(dev
);
337 data
= mt76x02_eeprom_get(dev
, MT_EE_VERSION
);
341 if (version
> MT76X0U_EE_MAX_VER
)
342 dev_warn(dev
->mt76
.dev
,
343 "Warning: unsupported EEPROM version %02hhx\n",
345 dev_info(dev
->mt76
.dev
, "EEPROM ver:%02hhx fae:%02hhx\n",
348 mt76x02_mac_setaddr(dev
, dev
->mt76
.eeprom
.data
+ MT_EE_MAC_ADDR
);
349 mt76x0_set_chip_cap(dev
);
350 mt76x0_set_freq_offset(dev
);
351 mt76x0_set_temp_offset(dev
);
356 MODULE_LICENSE("Dual BSD/GPL");