Linux-libre 5.4.49-gnu
[librecmc/linux-libre.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
97         val = FIELD_GET(MT_EE_NIC_WIFI_CONF_BAND_SEL,
98                         eeprom[MT_EE_WIFI_CONF]);
99         switch (val) {
100         case MT_EE_5GHZ:
101                 dev->mt76.cap.has_5ghz = true;
102                 break;
103         case MT_EE_2GHZ:
104                 dev->mt76.cap.has_2ghz = true;
105                 break;
106         default:
107                 dev->mt76.cap.has_2ghz = true;
108                 dev->mt76.cap.has_5ghz = true;
109                 break;
110         }
111 }
112
113 int mt7615_eeprom_get_power_index(struct mt7615_dev *dev,
114                                   struct ieee80211_channel *chan,
115                                   u8 chain_idx)
116 {
117         int index;
118
119         if (chain_idx > 3)
120                 return -EINVAL;
121
122         /* TSSI disabled */
123         if (mt7615_ext_pa_enabled(dev, chan->band)) {
124                 if (chan->band == NL80211_BAND_2GHZ)
125                         return MT_EE_EXT_PA_2G_TARGET_POWER;
126                 else
127                         return MT_EE_EXT_PA_5G_TARGET_POWER;
128         }
129
130         /* TSSI enabled */
131         if (chan->band == NL80211_BAND_2GHZ) {
132                 index = MT_EE_TX0_2G_TARGET_POWER + chain_idx * 6;
133         } else {
134                 int group = mt7615_get_channel_group(chan->hw_value);
135
136                 switch (chain_idx) {
137                 case 1:
138                         index = MT_EE_TX1_5G_G0_TARGET_POWER;
139                         break;
140                 case 2:
141                         index = MT_EE_TX2_5G_G0_TARGET_POWER;
142                         break;
143                 case 3:
144                         index = MT_EE_TX3_5G_G0_TARGET_POWER;
145                         break;
146                 case 0:
147                 default:
148                         index = MT_EE_TX0_5G_G0_TARGET_POWER;
149                         break;
150                 }
151                 index += 5 * group;
152         }
153
154         return index;
155 }
156
157 static void mt7615_apply_cal_free_data(struct mt7615_dev *dev)
158 {
159         static const u16 ical[] = {
160                 0x53, 0x54, 0x55, 0x56, 0x57, 0x5c, 0x5d, 0x62, 0x63, 0x68,
161                 0x69, 0x6e, 0x6f, 0x73, 0x74, 0x78, 0x79, 0x82, 0x83, 0x87,
162                 0x88, 0x8c, 0x8d, 0x91, 0x92, 0x96, 0x97, 0x9b, 0x9c, 0xa0,
163                 0xa1, 0xaa, 0xab, 0xaf, 0xb0, 0xb4, 0xb5, 0xb9, 0xba, 0xf4,
164                 0xf7, 0xff,
165                 0x140, 0x141, 0x145, 0x146, 0x14a, 0x14b, 0x154, 0x155, 0x159,
166                 0x15a, 0x15e, 0x15f, 0x163, 0x164, 0x168, 0x169, 0x16d, 0x16e,
167                 0x172, 0x173, 0x17c, 0x17d, 0x181, 0x182, 0x186, 0x187, 0x18b,
168                 0x18c
169         };
170         static const u16 ical_nocheck[] = {
171                 0x110, 0x111, 0x112, 0x113, 0x114, 0x115, 0x116, 0x117, 0x118,
172                 0x1b5, 0x1b6, 0x1b7, 0x3ac, 0x3ad, 0x3ae, 0x3af, 0x3b0, 0x3b1,
173                 0x3b2
174         };
175         u8 *eeprom = dev->mt76.eeprom.data;
176         u8 *otp = dev->mt76.otp.data;
177         int i;
178
179         if (!otp)
180                 return;
181
182         for (i = 0; i < ARRAY_SIZE(ical); i++)
183                 if (!otp[ical[i]])
184                         return;
185
186         for (i = 0; i < ARRAY_SIZE(ical); i++)
187                 eeprom[ical[i]] = otp[ical[i]];
188
189         for (i = 0; i < ARRAY_SIZE(ical_nocheck); i++)
190                 eeprom[ical_nocheck[i]] = otp[ical_nocheck[i]];
191 }
192
193 int mt7615_eeprom_init(struct mt7615_dev *dev)
194 {
195         int ret;
196
197         ret = mt7615_eeprom_load(dev);
198         if (ret < 0)
199                 return ret;
200
201         ret = mt7615_check_eeprom(&dev->mt76);
202         if (ret && dev->mt76.otp.data)
203                 memcpy(dev->mt76.eeprom.data, dev->mt76.otp.data,
204                        MT7615_EEPROM_SIZE);
205         else
206                 mt7615_apply_cal_free_data(dev);
207
208         mt7615_eeprom_parse_hw_cap(dev);
209         memcpy(dev->mt76.macaddr, dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
210                ETH_ALEN);
211
212         mt76_eeprom_override(&dev->mt76);
213
214         return 0;
215 }