eccad4987ac830c596748401c03459e6c053d586
[linux-2.6-microblaze.git] / drivers / net / wireless / mediatek / mt76 / mt7615 / eeprom.c
1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2019 MediaTek Inc.
3  *
4  * Author: Ryder Lee <ryder.lee@mediatek.com>
5  *         Felix Fietkau <nbd@nbd.name>
6  */
7
8 #include "mt7615.h"
9 #include "eeprom.h"
10
11 static 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
43 static 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
70 static 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
81 static 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
93 static void mt7615_eeprom_parse_hw_cap(struct mt7615_dev *dev)
94 {
95         u8 val, *eeprom = dev->mt76.eeprom.data;
96         u8 tx_mask, rx_mask, max_nss;
97
98         val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
99                         eeprom[MT_EE_WIFI_CONF]);
100         switch (val) {
101         case MT_EE_5GHZ:
102                 dev->mt76.cap.has_5ghz = true;
103                 break;
104         case MT_EE_2GHZ:
105                 dev->mt76.cap.has_2ghz = true;
106                 break;
107         default:
108                 dev->mt76.cap.has_2ghz = true;
109                 dev->mt76.cap.has_5ghz = true;
110                 break;
111         }
112
113         /* read tx-rx mask from eeprom */
114         val = mt76_rr(dev, MT_TOP_STRAP_STA);
115         max_nss = val & MT_TOP_3NSS ? 3 : 4;
116
117         rx_mask =  FIELD_GET(MT_EE_NIC_CONF_RX_MASK,
118                              eeprom[MT_EE_NIC_CONF_0]);
119         if (!rx_mask || rx_mask > max_nss)
120                 rx_mask = max_nss;
121
122         tx_mask =  FIELD_GET(MT_EE_NIC_CONF_TX_MASK,
123                              eeprom[MT_EE_NIC_CONF_0]);
124         if (!tx_mask || tx_mask > max_nss)
125                 tx_mask = max_nss;
126
127         dev->mt76.chainmask = tx_mask << 8 | rx_mask;
128         dev->mt76.antenna_mask = BIT(tx_mask) - 1;
129 }
130
131 int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
132                                   struct ieee80211_channel *chan,
133                                   u8 chain_idx)
134 {
135         int index;
136
137         if (chain_idx > 3)
138                 return -EINVAL;
139
140         /* TSSI disabled */
141         if (mt7615_ext_pa_enabled(dev, chan->band)) {
142                 if (chan->band == NL80211_BAND_2GHZ)
143                         return MT_EE_EXT_PA_2G_TARGET_POWER;
144                 else
145                         return MT_EE_EXT_PA_5G_TARGET_POWER;
146         }
147
148         /* TSSI enabled */
149         if (chan->band == NL80211_BAND_2GHZ) {
150                 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
151         } else {
152                 int group = mt7615_get_channel_group(chan->hw_value);
153
154                 switch (chain_idx) {
155                 case 1:
156                         index = MT_EE_TX1_5G_G0_TARGET_POWER;
157                         break;
158                 case 2:
159                         index = MT_EE_TX2_5G_G0_TARGET_POWER;
160                         break;
161                 case 3:
162                         index = MT_EE_TX3_5G_G0_TARGET_POWER;
163                         break;
164                 case 0:
165                 default:
166                         index = MT_EE_TX0_5G_G0_TARGET_POWER;
167                         break;
168                 }
169                 index += 5 * group;
170         }
171
172         return index;
173 }
174
175 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
176 {
177         static const u16 ical[] = {
178                 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
179                 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
180                 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
181                 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
182                 0xf7, 0xff,
183                 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
184                 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
185                 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
186                 0x18c
187         };
188         static const u16 ical_nocheck[] = {
189                 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
190                 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
191                 0x3b2
192         };
193         u8 *eeprom = dev->mt76.eeprom.data;
194         u8 *otp = dev->mt76.otp.data;
195         int i;
196
197         if (!otp)
198                 return;
199
200         for (i = 0; i < ARRAY_SIZE(ical); i++)
201                 if (!otp[ical[i]])
202                         return;
203
204         for (i = 0; i < ARRAY_SIZE(ical); i++)
205                 eeprom[ical[i]] = otp[ical[i]];
206
207         for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
208                 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
209 }
210
211 int mt7615_eeprom_init(struct mt7615_dev *dev)
212 {
213         int ret;
214
215         ret = mt7615_eeprom_load(dev);
216         if (ret < 0)
217                 return ret;
218
219         ret = mt7615_check_eeprom(&dev->mt76);
220         if (ret && dev->mt76.otp.data)
221                 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
222                        MT7615_EEPROM_SIZE);
223         else
224                 mt7615_apply_cal_free_data(dev);
225
226         mt7615_eeprom_parse_hw_cap(dev);
227         memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
228                ETH_ALEN);
229
230         mt76_eeprom_override(&dev->mt76);
231
232         return 0;
233 }