xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/mediatek/mt7601u/eeprom.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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