1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2020 MediaTek Inc. */
7 static u32
mt7915_eeprom_read(struct mt7915_dev
*dev
, u32 offset
)
9 u8
*data
= dev
->mt76
.eeprom
.data
;
11 if (data
[offset
] == 0xff)
12 mt7915_mcu_get_eeprom(dev
, offset
);
17 static int mt7915_eeprom_load(struct mt7915_dev
*dev
)
21 ret
= mt76_eeprom_init(&dev
->mt76
, MT7915_EEPROM_SIZE
);
25 memset(dev
->mt76
.eeprom
.data
, -1, MT7915_EEPROM_SIZE
);
30 static int mt7915_check_eeprom(struct mt7915_dev
*dev
)
32 u8
*eeprom
= dev
->mt76
.eeprom
.data
;
35 mt7915_eeprom_read(dev
, MT_EE_CHIP_ID
);
36 val
= get_unaligned_le16(eeprom
);
46 void mt7915_eeprom_parse_band_config(struct mt7915_phy
*phy
)
48 struct mt7915_dev
*dev
= phy
->dev
;
49 bool ext_phy
= phy
!= &dev
->phy
;
52 val
= mt7915_eeprom_read(dev
, MT_EE_WIFI_CONF
+ ext_phy
);
53 val
= FIELD_GET(MT_EE_WIFI_CONF_BAND_SEL
, val
);
56 phy
->mt76
->cap
.has_5ghz
= true;
59 phy
->mt76
->cap
.has_2ghz
= true;
62 phy
->mt76
->cap
.has_2ghz
= true;
63 phy
->mt76
->cap
.has_5ghz
= true;
68 static void mt7915_eeprom_parse_hw_cap(struct mt7915_dev
*dev
)
70 u8 nss
, tx_mask
[2] = {}, *eeprom
= dev
->mt76
.eeprom
.data
;
72 mt7915_eeprom_parse_band_config(&dev
->phy
);
74 /* read tx mask from eeprom */
75 tx_mask
[0] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK
,
76 eeprom
[MT_EE_WIFI_CONF
]);
77 if (dev
->dbdc_support
)
78 tx_mask
[1] = FIELD_GET(MT_EE_WIFI_CONF_TX_MASK
,
79 eeprom
[MT_EE_WIFI_CONF
+ 1]);
81 nss
= tx_mask
[0] + tx_mask
[1];
82 if (!nss
|| nss
> 4) {
87 dev
->chainmask
= BIT(nss
) - 1;
88 dev
->mphy
.antenna_mask
= BIT(tx_mask
[0]) - 1;
89 dev
->phy
.chainmask
= dev
->mphy
.antenna_mask
;
92 int mt7915_eeprom_init(struct mt7915_dev
*dev
)
96 ret
= mt7915_eeprom_load(dev
);
100 ret
= mt7915_check_eeprom(dev
);
104 mt7915_eeprom_parse_hw_cap(dev
);
105 memcpy(dev
->mphy
.macaddr
, dev
->mt76
.eeprom
.data
+ MT_EE_MAC_ADDR
,
108 mt76_eeprom_override(&dev
->mphy
);
113 int mt7915_eeprom_get_target_power(struct mt7915_dev
*dev
,
114 struct ieee80211_channel
*chan
,
123 tssi_on
= mt7915_tssi_enabled(dev
, chan
->band
);
125 if (chan
->band
== NL80211_BAND_2GHZ
) {
126 index
= MT_EE_TX0_POWER_2G
+ chain_idx
* 3 + !tssi_on
;
128 int group
= tssi_on
?
129 mt7915_get_channel_group(chan
->hw_value
) : 8;
131 index
= MT_EE_TX0_POWER_5G
+ chain_idx
* 12 + group
;
134 return mt7915_eeprom_read(dev
, index
);
137 static const u8 sku_cck_delta_map
[] = {
144 static const u8 sku_ofdm_delta_map
[] = {
155 static const u8 sku_mcs_delta_map
[] = {
170 #define SKU_GROUP(_mode, _len, _ofs_2g, _ofs_5g, _map) \
180 const struct sku_group mt7915_sku_groups
[] = {
181 SKU_GROUP(SKU_CCK
, 4, 0x252, 0, sku_cck_delta_map
),
182 SKU_GROUP(SKU_OFDM
, 8, 0x254, 0x29d, sku_ofdm_delta_map
),
184 SKU_GROUP(SKU_HT_BW20
, 8, 0x259, 0x2a2, sku_mcs_delta_map
),
185 SKU_GROUP(SKU_HT_BW40
, 9, 0x262, 0x2ab, sku_mcs_delta_map
),
186 SKU_GROUP(SKU_VHT_BW20
, 12, 0x259, 0x2a2, sku_mcs_delta_map
),
187 SKU_GROUP(SKU_VHT_BW40
, 12, 0x262, 0x2ab, sku_mcs_delta_map
),
188 SKU_GROUP(SKU_VHT_BW80
, 12, 0, 0x2b4, sku_mcs_delta_map
),
189 SKU_GROUP(SKU_VHT_BW160
, 12, 0, 0, sku_mcs_delta_map
),
191 SKU_GROUP(SKU_HE_RU26
, 12, 0x27f, 0x2dd, sku_mcs_delta_map
),
192 SKU_GROUP(SKU_HE_RU52
, 12, 0x289, 0x2e7, sku_mcs_delta_map
),
193 SKU_GROUP(SKU_HE_RU106
, 12, 0x293, 0x2f1, sku_mcs_delta_map
),
194 SKU_GROUP(SKU_HE_RU242
, 12, 0x26b, 0x2bf, sku_mcs_delta_map
),
195 SKU_GROUP(SKU_HE_RU484
, 12, 0x275, 0x2c9, sku_mcs_delta_map
),
196 SKU_GROUP(SKU_HE_RU996
, 12, 0, 0x2d3, sku_mcs_delta_map
),
197 SKU_GROUP(SKU_HE_RU2x996
, 12, 0, 0, sku_mcs_delta_map
),
201 mt7915_get_sku_delta(struct mt7915_dev
*dev
, u32 addr
)
203 u32 val
= mt7915_eeprom_read(dev
, addr
);
204 s8 delta
= FIELD_GET(SKU_DELTA_VAL
, val
);
206 if (!(val
& SKU_DELTA_EN
))
209 return val
& SKU_DELTA_ADD
? delta
: -delta
;
213 mt7915_eeprom_init_sku_band(struct mt7915_dev
*dev
,
214 struct ieee80211_supported_band
*sband
)
216 int i
, band
= sband
->band
;
217 s8
*rate_power
= dev
->rate_power
[band
], max_delta
= 0;
220 for (i
= 0; i
< ARRAY_SIZE(mt7915_sku_groups
); i
++) {
221 const struct sku_group
*sku
= &mt7915_sku_groups
[i
];
222 u32 offset
= sku
->offset
[band
];
230 rate_power
[idx
++] = mt7915_get_sku_delta(dev
, offset
);
231 if (rate_power
[idx
- 1] > max_delta
)
232 max_delta
= rate_power
[idx
- 1];
234 if (i
== SKU_HT_BW20
|| i
== SKU_VHT_BW20
)
237 for (j
= 1; j
< sku
->len
; j
++) {
238 u32 addr
= offset
+ sku
->delta_map
[j
];
240 rate_power
[idx
++] = mt7915_get_sku_delta(dev
, addr
);
241 if (rate_power
[idx
- 1] > max_delta
)
242 max_delta
= rate_power
[idx
- 1];
246 rate_power
[idx
] = max_delta
;
249 void mt7915_eeprom_init_sku(struct mt7915_dev
*dev
)
251 mt7915_eeprom_init_sku_band(dev
, &dev
->mphy
.sband_2g
.sband
);
252 mt7915_eeprom_init_sku_band(dev
, &dev
->mphy
.sband_5g
.sband
);