Path: blob/main/sys/contrib/dev/mediatek/mt76/mt76x02_eeprom.c
48378 views
// SPDX-License-Identifier: ISC1/*2* Copyright (C) 2016 Felix Fietkau <[email protected]>3* Copyright (C) 2018 Lorenzo Bianconi <[email protected]>4*/56#include <linux/unaligned.h>78#include "mt76x02_eeprom.h"910static int11mt76x02_efuse_read(struct mt76x02_dev *dev, u16 addr, u8 *data,12enum mt76x02_eeprom_modes mode)13{14u32 val;15int i;1617val = mt76_rr(dev, MT_EFUSE_CTRL);18val &= ~(MT_EFUSE_CTRL_AIN |19MT_EFUSE_CTRL_MODE);20val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf);21val |= FIELD_PREP(MT_EFUSE_CTRL_MODE, mode);22val |= MT_EFUSE_CTRL_KICK;23mt76_wr(dev, MT_EFUSE_CTRL, val);2425if (!mt76_poll_msec(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000))26return -ETIMEDOUT;2728udelay(2);2930val = mt76_rr(dev, MT_EFUSE_CTRL);31if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) {32memset(data, 0xff, 16);33return 0;34}3536for (i = 0; i < 4; i++) {37val = mt76_rr(dev, MT_EFUSE_DATA(i));38put_unaligned_le32(val, data + 4 * i);39}4041return 0;42}4344int mt76x02_eeprom_copy(struct mt76x02_dev *dev,45enum mt76x02_eeprom_field field,46void *dest, int len)47{48if (field + len > dev->mt76.eeprom.size)49return -1;5051memcpy(dest, dev->mt76.eeprom.data + field, len);52return 0;53}54EXPORT_SYMBOL_GPL(mt76x02_eeprom_copy);5556int mt76x02_get_efuse_data(struct mt76x02_dev *dev, u16 base, void *buf,57int len, enum mt76x02_eeprom_modes mode)58{59int ret, i;6061for (i = 0; i + 16 <= len; i += 16) {62ret = mt76x02_efuse_read(dev, base + i, buf + i, mode);63if (ret)64return ret;65}6667return 0;68}69EXPORT_SYMBOL_GPL(mt76x02_get_efuse_data);7071void mt76x02_eeprom_parse_hw_cap(struct mt76x02_dev *dev)72{73u16 val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);7475switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, val)) {76case BOARD_TYPE_5GHZ:77dev->mphy.cap.has_5ghz = true;78break;79case BOARD_TYPE_2GHZ:80dev->mphy.cap.has_2ghz = true;81break;82default:83dev->mphy.cap.has_2ghz = true;84dev->mphy.cap.has_5ghz = true;85break;86}87}88EXPORT_SYMBOL_GPL(mt76x02_eeprom_parse_hw_cap);8990bool mt76x02_ext_pa_enabled(struct mt76x02_dev *dev, enum nl80211_band band)91{92u16 conf0 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_0);9394if (band == NL80211_BAND_5GHZ)95return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_5G);96else97return !(conf0 & MT_EE_NIC_CONF_0_PA_INT_2G);98}99EXPORT_SYMBOL_GPL(mt76x02_ext_pa_enabled);100101void mt76x02_get_rx_gain(struct mt76x02_dev *dev, enum nl80211_band band,102u16 *rssi_offset, s8 *lna_2g, s8 *lna_5g)103{104u16 val;105106val = mt76x02_eeprom_get(dev, MT_EE_LNA_GAIN);107*lna_2g = val & 0xff;108lna_5g[0] = val >> 8;109110val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_1);111lna_5g[1] = val >> 8;112113val = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_1);114lna_5g[2] = val >> 8;115116if (!mt76x02_field_valid(lna_5g[1]))117lna_5g[1] = lna_5g[0];118119if (!mt76x02_field_valid(lna_5g[2]))120lna_5g[2] = lna_5g[0];121122if (band == NL80211_BAND_2GHZ)123*rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_2G_0);124else125*rssi_offset = mt76x02_eeprom_get(dev, MT_EE_RSSI_OFFSET_5G_0);126}127EXPORT_SYMBOL_GPL(mt76x02_get_rx_gain);128129u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev,130s8 *lna_2g, s8 *lna_5g,131struct ieee80211_channel *chan)132{133u8 lna;134135if (chan->band == NL80211_BAND_2GHZ)136lna = *lna_2g;137else if (chan->hw_value <= 64)138lna = lna_5g[0];139else if (chan->hw_value <= 128)140lna = lna_5g[1];141else142lna = lna_5g[2];143144return lna != 0xff ? lna : 0;145}146EXPORT_SYMBOL_GPL(mt76x02_get_lna_gain);147148149