1
2
3
4
5
6
7
8#include "mt7615.h"
9#include "eeprom.h"
10
11static int mt7615_efuse_read(struct mt7615_dev *dev, u32 base,
12 u16 addr, u8 *data)
13{
14 u32 val;
15 int i;
16
17 val = mt76_rr(dev, base + MT_EFUSE_CTRL);
18 val &= ~(MT_EFUSE_CTRL_AIN | MT_EFUSE_CTRL_MODE);
19 val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);
20 val |= MT_EFUSE_CTRL_KICK;
21 mt76_wr(dev, base + MT_EFUSE_CTRL, val);
22
23 if (!mt76_poll(dev, base + MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
24 return -ETIMEDOUT;
25
26 udelay(2);
27
28 val = mt76_rr(dev, base + MT_EFUSE_CTRL);
29 if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT ||
30 WARN_ON_ONCE(!(val & MT_EFUSE_CTRL_VALID))) {
31 memset(data, 0x0, 16);
32 return 0;
33 }
34
35 for (i = 0; i < 4; i++) {
36 val = mt76_rr(dev, base + MT_EFUSE_RDATA(i));
37 put_unaligned_le32(val, data + 4 * i);
38 }
39
40 return 0;
41}
42
43static int mt7615_efuse_init(struct mt7615_dev *dev)
44{
45 u32 val, base = mt7615_reg_map(dev, MT_EFUSE_BASE);
46 int i, len = MT7615_EEPROM_SIZE;
47 void *buf;
48
49 val = mt76_rr(dev, base + MT_EFUSE_BASE_CTRL);
50 if (val & MT_EFUSE_BASE_CTRL_EMPTY)
51 return 0;
52
53 dev->mt76.otp.data = devm_kzalloc(dev->mt76.dev, len, GFP_KERNEL);
54 dev->mt76.otp.size = len;
55 if (!dev->mt76.otp.data)
56 return -ENOMEM;
57
58 buf = dev->mt76.otp.data;
59 for (i = 0; i + 16 <= len; i += 16) {
60 int ret;
61
62 ret = mt7615_efuse_read(dev, base, i, buf + i);
63 if (ret)
64 return ret;
65 }
66
67 return 0;
68}
69
70static int mt7615_eeprom_load(struct mt7615_dev *dev)
71{
72 int ret;
73
74 ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE);
75 if (ret < 0)
76 return ret;
77
78 return mt7615_efuse_init(dev);
79}
80
81static int mt7615_check_eeprom(struct mt76_dev *dev)
82{
83 u16 val = get_unaligned_le16(dev->eeprom.data);
84
85 switch (val) {
86 case 0x7615:
87 return 0;
88 default:
89 return -EINVAL;
90 }
91}
92
93static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
94{
95 u8 *eeprom = dev->mt76.eeprom.data;
96 u8 tx_mask, rx_mask, max_nss;
97 u32 val;
98
99 val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
100 eeprom[MT_EE_WIFI_CONF]);
101 switch (val) {
102 case MT_EE_5GHZ:
103 dev->mt76.cap.has_5ghz = true;
104 break;
105 case MT_EE_2GHZ:
106 dev->mt76.cap.has_2ghz = true;
107 break;
108 default:
109 dev->mt76.cap.has_2ghz = true;
110 dev->mt76.cap.has_5ghz = true;
111 break;
112 }
113
114
115 val = mt76_rr(dev, MT_TOP_STRAP_STA);
116 max_nss = val & MT_TOP_3NSS ? 3 : 4;
117
118 rx_mask = FIELD_GET(MT_EE_NIC_CONF_RX_MASK,
119 eeprom[MT_EE_NIC_CONF_0]);
120 if (!rx_mask || rx_mask > max_nss)
121 rx_mask = max_nss;
122
123 tx_mask = FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
124 eeprom[MT_EE_NIC_CONF_0]);
125 if (!tx_mask || tx_mask > max_nss)
126 tx_mask = max_nss;
127
128 dev->mt76.chainmask = tx_mask << 8 | rx_mask;
129 dev->mt76.antenna_mask = BIT(tx_mask) - 1;
130}
131
132int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
133 struct ieee80211_channel *chan,
134 u8 chain_idx)
135{
136 int index;
137
138 if (chain_idx > 3)
139 return -EINVAL;
140
141
142 if (mt7615_ext_pa_enabled(dev, chan->band)) {
143 if (chan->band == NL80211_BAND_2GHZ)
144 return MT_EE_EXT_PA_2G_TARGET_POWER;
145 else
146 return MT_EE_EXT_PA_5G_TARGET_POWER;
147 }
148
149
150 if (chan->band == NL80211_BAND_2GHZ) {
151 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
152 } else {
153 int group = mt7615_get_channel_group(chan->hw_value);
154
155 switch (chain_idx) {
156 case 1:
157 index = MT_EE_TX1_5G_G0_TARGET_POWER;
158 break;
159 case 2:
160 index = MT_EE_TX2_5G_G0_TARGET_POWER;
161 break;
162 case 3:
163 index = MT_EE_TX3_5G_G0_TARGET_POWER;
164 break;
165 case 0:
166 default:
167 index = MT_EE_TX0_5G_G0_TARGET_POWER;
168 break;
169 }
170 index += 5 * group;
171 }
172
173 return index;
174}
175
176static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
177{
178 static const u16 ical[] = {
179 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
180 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
181 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
182 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
183 0xf7, 0xff,
184 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
185 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
186 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
187 0x18c
188 };
189 static const u16 ical_nocheck[] = {
190 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
191 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
192 0x3b2
193 };
194 u8 *eeprom = dev->mt76.eeprom.data;
195 u8 *otp = dev->mt76.otp.data;
196 int i;
197
198 if (!otp)
199 return;
200
201 for (i = 0; i < ARRAY_SIZE(ical); i++)
202 if (!otp[ical[i]])
203 return;
204
205 for (i = 0; i < ARRAY_SIZE(ical); i++)
206 eeprom[ical[i]] = otp[ical[i]];
207
208 for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
209 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
210}
211
212int mt7615_eeprom_init(struct mt7615_dev *dev)
213{
214 int ret;
215
216 ret = mt7615_eeprom_load(dev);
217 if (ret < 0)
218 return ret;
219
220 ret = mt7615_check_eeprom(&dev->mt76);
221 if (ret && dev->mt76.otp.data)
222 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
223 MT7615_EEPROM_SIZE);
224 else
225 mt7615_apply_cal_free_data(dev);
226
227 mt7615_eeprom_parse_hw_cap(dev);
228 memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
229 ETH_ALEN);
230
231 mt76_eeprom_override(&dev->mt76);
232
233 return 0;
234}
235