1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org>
4*4882a593Smuzhiyun * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl>
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <linux/of.h>
8*4882a593Smuzhiyun #include <linux/mtd/mtd.h>
9*4882a593Smuzhiyun #include <linux/mtd/partitions.h>
10*4882a593Smuzhiyun #include <linux/etherdevice.h>
11*4882a593Smuzhiyun #include <asm/unaligned.h>
12*4882a593Smuzhiyun #include "mt7601u.h"
13*4882a593Smuzhiyun #include "eeprom.h"
14*4882a593Smuzhiyun #include "mac.h"
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun static bool
field_valid(u8 val)17*4882a593Smuzhiyun field_valid(u8 val)
18*4882a593Smuzhiyun {
19*4882a593Smuzhiyun return val != 0xff;
20*4882a593Smuzhiyun }
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun static s8
field_validate(u8 val)23*4882a593Smuzhiyun field_validate(u8 val)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun if (!field_valid(val))
26*4882a593Smuzhiyun return 0;
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun return val;
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun static int
mt7601u_efuse_read(struct mt7601u_dev * dev,u16 addr,u8 * data,enum mt7601u_eeprom_access_modes mode)32*4882a593Smuzhiyun mt7601u_efuse_read(struct mt7601u_dev *dev, u16 addr, u8 *data,
33*4882a593Smuzhiyun enum mt7601u_eeprom_access_modes mode)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun u32 val;
36*4882a593Smuzhiyun int i;
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun val = mt76_rr(dev, MT_EFUSE_CTRL);
39*4882a593Smuzhiyun val &= ~(MT_EFUSE_CTRL_AIN |
40*4882a593Smuzhiyun MT_EFUSE_CTRL_MODE);
41*4882a593Smuzhiyun val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf) |
42*4882a593Smuzhiyun FIELD_PREP(MT_EFUSE_CTRL_MODE, mode) |
43*4882a593Smuzhiyun MT_EFUSE_CTRL_KICK;
44*4882a593Smuzhiyun mt76_wr(dev, MT_EFUSE_CTRL, val);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))
47*4882a593Smuzhiyun return -ETIMEDOUT;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun val = mt76_rr(dev, MT_EFUSE_CTRL);
50*4882a593Smuzhiyun if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {
51*4882a593Smuzhiyun /* Parts of eeprom not in the usage map (0x80-0xc0,0xf0)
52*4882a593Smuzhiyun * will not return valid data but it's ok.
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun memset(data, 0xff, 16);
55*4882a593Smuzhiyun return 0;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
59*4882a593Smuzhiyun val = mt76_rr(dev, MT_EFUSE_DATA(i));
60*4882a593Smuzhiyun put_unaligned_le32(val, data + 4 * i);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun return 0;
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static int
mt7601u_efuse_physical_size_check(struct mt7601u_dev * dev)67*4882a593Smuzhiyun mt7601u_efuse_physical_size_check(struct mt7601u_dev *dev)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun const int map_reads = DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16);
70*4882a593Smuzhiyun u8 data[round_up(MT_EFUSE_USAGE_MAP_SIZE, 16)];
71*4882a593Smuzhiyun int ret, i;
72*4882a593Smuzhiyun u32 start = 0, end = 0, cnt_free;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun for (i = 0; i < map_reads; i++) {
75*4882a593Smuzhiyun ret = mt7601u_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16,
76*4882a593Smuzhiyun data + i * 16, MT_EE_PHYSICAL_READ);
77*4882a593Smuzhiyun if (ret)
78*4882a593Smuzhiyun return ret;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++)
82*4882a593Smuzhiyun if (!data[i]) {
83*4882a593Smuzhiyun if (!start)
84*4882a593Smuzhiyun start = MT_EE_USAGE_MAP_START + i;
85*4882a593Smuzhiyun end = MT_EE_USAGE_MAP_START + i;
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun cnt_free = end - start + 1;
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) {
90*4882a593Smuzhiyun dev_err(dev->dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n");
91*4882a593Smuzhiyun return -EINVAL;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun return 0;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun static bool
mt7601u_has_tssi(struct mt7601u_dev * dev,u8 * eeprom)98*4882a593Smuzhiyun mt7601u_has_tssi(struct mt7601u_dev *dev, u8 *eeprom)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun return (u16)~nic_conf1 && (nic_conf1 & MT_EE_NIC_CONF_1_TX_ALC_EN);
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun static void
mt7601u_set_chip_cap(struct mt7601u_dev * dev,u8 * eeprom)106*4882a593Smuzhiyun mt7601u_set_chip_cap(struct mt7601u_dev *dev, u8 *eeprom)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0);
109*4882a593Smuzhiyun u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1);
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun if (!field_valid(nic_conf1 & 0xff))
112*4882a593Smuzhiyun nic_conf1 &= 0xff00;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun dev->ee->tssi_enabled = mt7601u_has_tssi(dev, eeprom) &&
115*4882a593Smuzhiyun !(nic_conf1 & MT_EE_NIC_CONF_1_TEMP_TX_ALC);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL)
118*4882a593Smuzhiyun dev_err(dev->dev,
119*4882a593Smuzhiyun "Error: this driver does not support HW RF ctrl\n");
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (!field_valid(nic_conf0 >> 8))
122*4882a593Smuzhiyun return;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 ||
125*4882a593Smuzhiyun FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1)
126*4882a593Smuzhiyun dev_err(dev->dev,
127*4882a593Smuzhiyun "Error: device has more than 1 RX/TX stream!\n");
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
mt7601u_set_channel_target_power(struct mt7601u_dev * dev,u8 * eeprom,u8 max_pwr)130*4882a593Smuzhiyun static void mt7601u_set_channel_target_power(struct mt7601u_dev *dev,
131*4882a593Smuzhiyun u8 *eeprom, u8 max_pwr)
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun u8 trgt_pwr = eeprom[MT_EE_TX_TSSI_TARGET_POWER];
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (trgt_pwr > max_pwr || !trgt_pwr) {
136*4882a593Smuzhiyun dev_warn(dev->dev, "Error: EEPROM trgt power invalid %hhx!\n",
137*4882a593Smuzhiyun trgt_pwr);
138*4882a593Smuzhiyun trgt_pwr = 0x20;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun memset(dev->ee->chan_pwr, trgt_pwr, sizeof(dev->ee->chan_pwr));
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun static void
mt7601u_set_channel_power(struct mt7601u_dev * dev,u8 * eeprom)145*4882a593Smuzhiyun mt7601u_set_channel_power(struct mt7601u_dev *dev, u8 *eeprom)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun u32 i, val;
148*4882a593Smuzhiyun u8 max_pwr;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun val = mt7601u_rr(dev, MT_TX_ALC_CFG_0);
151*4882a593Smuzhiyun max_pwr = FIELD_GET(MT_TX_ALC_CFG_0_LIMIT_0, val);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun if (mt7601u_has_tssi(dev, eeprom)) {
154*4882a593Smuzhiyun mt7601u_set_channel_target_power(dev, eeprom, max_pwr);
155*4882a593Smuzhiyun return;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun for (i = 0; i < 14; i++) {
159*4882a593Smuzhiyun s8 power = field_validate(eeprom[MT_EE_TX_POWER_OFFSET + i]);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (power > max_pwr || power < 0)
162*4882a593Smuzhiyun power = MT7601U_DEFAULT_TX_POWER;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun dev->ee->chan_pwr[i] = power;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun static void
mt7601u_set_country_reg(struct mt7601u_dev * dev,u8 * eeprom)169*4882a593Smuzhiyun mt7601u_set_country_reg(struct mt7601u_dev *dev, u8 *eeprom)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun /* Note: - region 31 is not valid for mt7601u (see rtmp_init.c)
172*4882a593Smuzhiyun * - comments in rtmp_def.h are incorrect (see rt_channel.c)
173*4882a593Smuzhiyun */
174*4882a593Smuzhiyun static const struct reg_channel_bounds chan_bounds[] = {
175*4882a593Smuzhiyun /* EEPROM country regions 0 - 7 */
176*4882a593Smuzhiyun { 1, 11 }, { 1, 13 }, { 10, 2 }, { 10, 4 },
177*4882a593Smuzhiyun { 14, 1 }, { 1, 14 }, { 3, 7 }, { 5, 9 },
178*4882a593Smuzhiyun /* EEPROM country regions 32 - 33 */
179*4882a593Smuzhiyun { 1, 11 }, { 1, 14 }
180*4882a593Smuzhiyun };
181*4882a593Smuzhiyun u8 val = eeprom[MT_EE_COUNTRY_REGION];
182*4882a593Smuzhiyun int idx = -1;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun if (val < 8)
185*4882a593Smuzhiyun idx = val;
186*4882a593Smuzhiyun if (val > 31 && val < 33)
187*4882a593Smuzhiyun idx = val - 32 + 8;
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun if (idx != -1)
190*4882a593Smuzhiyun dev_info(dev->dev,
191*4882a593Smuzhiyun "EEPROM country region %02hhx (channels %hhd-%hhd)\n",
192*4882a593Smuzhiyun val, chan_bounds[idx].start,
193*4882a593Smuzhiyun chan_bounds[idx].start + chan_bounds[idx].num - 1);
194*4882a593Smuzhiyun else
195*4882a593Smuzhiyun idx = 5; /* channels 1 - 14 */
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun dev->ee->reg = chan_bounds[idx];
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /* TODO: country region 33 is special - phy should be set to B-mode
200*4882a593Smuzhiyun * before entering channel 14 (see sta/connect.c)
201*4882a593Smuzhiyun */
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun static void
mt7601u_set_rf_freq_off(struct mt7601u_dev * dev,u8 * eeprom)205*4882a593Smuzhiyun mt7601u_set_rf_freq_off(struct mt7601u_dev *dev, u8 *eeprom)
206*4882a593Smuzhiyun {
207*4882a593Smuzhiyun u8 comp;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun dev->ee->rf_freq_off = field_validate(eeprom[MT_EE_FREQ_OFFSET]);
210*4882a593Smuzhiyun comp = field_validate(eeprom[MT_EE_FREQ_OFFSET_COMPENSATION]);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun if (comp & BIT(7))
213*4882a593Smuzhiyun dev->ee->rf_freq_off -= comp & 0x7f;
214*4882a593Smuzhiyun else
215*4882a593Smuzhiyun dev->ee->rf_freq_off += comp;
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun static void
mt7601u_set_rssi_offset(struct mt7601u_dev * dev,u8 * eeprom)219*4882a593Smuzhiyun mt7601u_set_rssi_offset(struct mt7601u_dev *dev, u8 *eeprom)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun int i;
222*4882a593Smuzhiyun s8 *rssi_offset = dev->ee->rssi_offset;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun for (i = 0; i < 2; i++) {
225*4882a593Smuzhiyun rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET + i];
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun if (rssi_offset[i] < -10 || rssi_offset[i] > 10) {
228*4882a593Smuzhiyun dev_warn(dev->dev,
229*4882a593Smuzhiyun "Warning: EEPROM RSSI is invalid %02hhx\n",
230*4882a593Smuzhiyun rssi_offset[i]);
231*4882a593Smuzhiyun rssi_offset[i] = 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun static void
mt7601u_extra_power_over_mac(struct mt7601u_dev * dev)237*4882a593Smuzhiyun mt7601u_extra_power_over_mac(struct mt7601u_dev *dev)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun u32 val;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun val = ((mt7601u_rr(dev, MT_TX_PWR_CFG_1) & 0x0000ff00) >> 8);
242*4882a593Smuzhiyun val |= ((mt7601u_rr(dev, MT_TX_PWR_CFG_2) & 0x0000ff00) << 8);
243*4882a593Smuzhiyun mt7601u_wr(dev, MT_TX_PWR_CFG_7, val);
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun val = ((mt7601u_rr(dev, MT_TX_PWR_CFG_4) & 0x0000ff00) >> 8);
246*4882a593Smuzhiyun mt7601u_wr(dev, MT_TX_PWR_CFG_9, val);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun static void
mt7601u_set_power_rate(struct power_per_rate * rate,s8 delta,u8 value)250*4882a593Smuzhiyun mt7601u_set_power_rate(struct power_per_rate *rate, s8 delta, u8 value)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun /* Invalid? Note: vendor driver does not handle this */
253*4882a593Smuzhiyun if (value == 0xff)
254*4882a593Smuzhiyun return;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun rate->raw = s6_validate(value);
257*4882a593Smuzhiyun rate->bw20 = s6_to_int(value);
258*4882a593Smuzhiyun /* Note: vendor driver does cap the value to s6 right away */
259*4882a593Smuzhiyun rate->bw40 = rate->bw20 + delta;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun static void
mt7601u_save_power_rate(struct mt7601u_dev * dev,s8 delta,u32 val,int i)263*4882a593Smuzhiyun mt7601u_save_power_rate(struct mt7601u_dev *dev, s8 delta, u32 val, int i)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun struct mt7601u_rate_power *t = &dev->ee->power_rate_table;
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun switch (i) {
268*4882a593Smuzhiyun case 0:
269*4882a593Smuzhiyun mt7601u_set_power_rate(&t->cck[0], delta, (val >> 0) & 0xff);
270*4882a593Smuzhiyun mt7601u_set_power_rate(&t->cck[1], delta, (val >> 8) & 0xff);
271*4882a593Smuzhiyun /* Save cck bw20 for fixups of channel 14 */
272*4882a593Smuzhiyun dev->ee->real_cck_bw20[0] = t->cck[0].bw20;
273*4882a593Smuzhiyun dev->ee->real_cck_bw20[1] = t->cck[1].bw20;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ofdm[0], delta, (val >> 16) & 0xff);
276*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ofdm[1], delta, (val >> 24) & 0xff);
277*4882a593Smuzhiyun break;
278*4882a593Smuzhiyun case 1:
279*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ofdm[2], delta, (val >> 0) & 0xff);
280*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ofdm[3], delta, (val >> 8) & 0xff);
281*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ht[0], delta, (val >> 16) & 0xff);
282*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ht[1], delta, (val >> 24) & 0xff);
283*4882a593Smuzhiyun break;
284*4882a593Smuzhiyun case 2:
285*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ht[2], delta, (val >> 0) & 0xff);
286*4882a593Smuzhiyun mt7601u_set_power_rate(&t->ht[3], delta, (val >> 8) & 0xff);
287*4882a593Smuzhiyun break;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun static s8
get_delta(u8 val)292*4882a593Smuzhiyun get_delta(u8 val)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun s8 ret;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun if (!field_valid(val) || !(val & BIT(7)))
297*4882a593Smuzhiyun return 0;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun ret = val & 0x1f;
300*4882a593Smuzhiyun if (ret > 8)
301*4882a593Smuzhiyun ret = 8;
302*4882a593Smuzhiyun if (val & BIT(6))
303*4882a593Smuzhiyun ret = -ret;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun return ret;
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun static void
mt7601u_config_tx_power_per_rate(struct mt7601u_dev * dev,u8 * eeprom)309*4882a593Smuzhiyun mt7601u_config_tx_power_per_rate(struct mt7601u_dev *dev, u8 *eeprom)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun u32 val;
312*4882a593Smuzhiyun s8 bw40_delta;
313*4882a593Smuzhiyun int i;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun bw40_delta = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40]);
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun for (i = 0; i < 5; i++) {
318*4882a593Smuzhiyun val = get_unaligned_le32(eeprom + MT_EE_TX_POWER_BYRATE(i));
319*4882a593Smuzhiyun
320*4882a593Smuzhiyun mt7601u_save_power_rate(dev, bw40_delta, val, i);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun if (~val)
323*4882a593Smuzhiyun mt7601u_wr(dev, MT_TX_PWR_CFG_0 + i * 4, val);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun mt7601u_extra_power_over_mac(dev);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun static void
mt7601u_init_tssi_params(struct mt7601u_dev * dev,u8 * eeprom)330*4882a593Smuzhiyun mt7601u_init_tssi_params(struct mt7601u_dev *dev, u8 *eeprom)
331*4882a593Smuzhiyun {
332*4882a593Smuzhiyun struct tssi_data *d = &dev->ee->tssi_data;
333*4882a593Smuzhiyun
334*4882a593Smuzhiyun if (!dev->ee->tssi_enabled)
335*4882a593Smuzhiyun return;
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun d->slope = eeprom[MT_EE_TX_TSSI_SLOPE];
338*4882a593Smuzhiyun d->tx0_delta_offset = eeprom[MT_EE_TX_TSSI_OFFSET] * 1024;
339*4882a593Smuzhiyun d->offset[0] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP];
340*4882a593Smuzhiyun d->offset[1] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP + 1];
341*4882a593Smuzhiyun d->offset[2] = eeprom[MT_EE_TX_TSSI_OFFSET_GROUP + 2];
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun int
mt7601u_eeprom_init(struct mt7601u_dev * dev)345*4882a593Smuzhiyun mt7601u_eeprom_init(struct mt7601u_dev *dev)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun u8 *eeprom;
348*4882a593Smuzhiyun int i, ret;
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun ret = mt7601u_efuse_physical_size_check(dev);
351*4882a593Smuzhiyun if (ret)
352*4882a593Smuzhiyun return ret;
353*4882a593Smuzhiyun
354*4882a593Smuzhiyun dev->ee = devm_kzalloc(dev->dev, sizeof(*dev->ee), GFP_KERNEL);
355*4882a593Smuzhiyun if (!dev->ee)
356*4882a593Smuzhiyun return -ENOMEM;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun eeprom = kmalloc(MT7601U_EEPROM_SIZE, GFP_KERNEL);
359*4882a593Smuzhiyun if (!eeprom)
360*4882a593Smuzhiyun return -ENOMEM;
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun for (i = 0; i + 16 <= MT7601U_EEPROM_SIZE; i += 16) {
363*4882a593Smuzhiyun ret = mt7601u_efuse_read(dev, i, eeprom + i, MT_EE_READ);
364*4882a593Smuzhiyun if (ret)
365*4882a593Smuzhiyun goto out;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun if (eeprom[MT_EE_VERSION_EE] > MT7601U_EE_MAX_VER)
369*4882a593Smuzhiyun dev_warn(dev->dev,
370*4882a593Smuzhiyun "Warning: unsupported EEPROM version %02hhx\n",
371*4882a593Smuzhiyun eeprom[MT_EE_VERSION_EE]);
372*4882a593Smuzhiyun dev_info(dev->dev, "EEPROM ver:%02hhx fae:%02hhx\n",
373*4882a593Smuzhiyun eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun mt7601u_set_macaddr(dev, eeprom + MT_EE_MAC_ADDR);
376*4882a593Smuzhiyun mt7601u_set_chip_cap(dev, eeprom);
377*4882a593Smuzhiyun mt7601u_set_channel_power(dev, eeprom);
378*4882a593Smuzhiyun mt7601u_set_country_reg(dev, eeprom);
379*4882a593Smuzhiyun mt7601u_set_rf_freq_off(dev, eeprom);
380*4882a593Smuzhiyun mt7601u_set_rssi_offset(dev, eeprom);
381*4882a593Smuzhiyun dev->ee->ref_temp = eeprom[MT_EE_REF_TEMP];
382*4882a593Smuzhiyun dev->ee->lna_gain = eeprom[MT_EE_LNA_GAIN];
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun mt7601u_config_tx_power_per_rate(dev, eeprom);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun mt7601u_init_tssi_params(dev, eeprom);
387*4882a593Smuzhiyun out:
388*4882a593Smuzhiyun kfree(eeprom);
389*4882a593Smuzhiyun return ret;
390*4882a593Smuzhiyun }
391