1*e87b5039SStanislaw Gruszka /* 2*e87b5039SStanislaw Gruszka * Copyright (C) 2014 Felix Fietkau <nbd@openwrt.org> 3*e87b5039SStanislaw Gruszka * Copyright (C) 2015 Jakub Kicinski <kubakici@wp.pl> 4*e87b5039SStanislaw Gruszka * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl> 5*e87b5039SStanislaw Gruszka * 6*e87b5039SStanislaw Gruszka * This program is free software; you can redistribute it and/or modify 7*e87b5039SStanislaw Gruszka * it under the terms of the GNU General Public License version 2 8*e87b5039SStanislaw Gruszka * as published by the Free Software Foundation 9*e87b5039SStanislaw Gruszka * 10*e87b5039SStanislaw Gruszka * This program is distributed in the hope that it will be useful, 11*e87b5039SStanislaw Gruszka * but WITHOUT ANY WARRANTY; without even the implied warranty of 12*e87b5039SStanislaw Gruszka * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13*e87b5039SStanislaw Gruszka * GNU General Public License for more details. 14*e87b5039SStanislaw Gruszka */ 15*e87b5039SStanislaw Gruszka 16*e87b5039SStanislaw Gruszka #include <linux/of.h> 17*e87b5039SStanislaw Gruszka #include <linux/mtd/mtd.h> 18*e87b5039SStanislaw Gruszka #include <linux/mtd/partitions.h> 19*e87b5039SStanislaw Gruszka #include <linux/etherdevice.h> 20*e87b5039SStanislaw Gruszka #include <asm/unaligned.h> 21*e87b5039SStanislaw Gruszka #include "mt76x0.h" 22*e87b5039SStanislaw Gruszka #include "eeprom.h" 23*e87b5039SStanislaw Gruszka 24*e87b5039SStanislaw Gruszka static bool 25*e87b5039SStanislaw Gruszka field_valid(u8 val) 26*e87b5039SStanislaw Gruszka { 27*e87b5039SStanislaw Gruszka return val != 0xff; 28*e87b5039SStanislaw Gruszka } 29*e87b5039SStanislaw Gruszka 30*e87b5039SStanislaw Gruszka static s8 31*e87b5039SStanislaw Gruszka field_validate(u8 val) 32*e87b5039SStanislaw Gruszka { 33*e87b5039SStanislaw Gruszka if (!field_valid(val)) 34*e87b5039SStanislaw Gruszka return 0; 35*e87b5039SStanislaw Gruszka 36*e87b5039SStanislaw Gruszka return val; 37*e87b5039SStanislaw Gruszka } 38*e87b5039SStanislaw Gruszka 39*e87b5039SStanislaw Gruszka static inline int 40*e87b5039SStanislaw Gruszka sign_extend(u32 val, unsigned int size) 41*e87b5039SStanislaw Gruszka { 42*e87b5039SStanislaw Gruszka bool sign = val & BIT(size - 1); 43*e87b5039SStanislaw Gruszka 44*e87b5039SStanislaw Gruszka val &= BIT(size - 1) - 1; 45*e87b5039SStanislaw Gruszka 46*e87b5039SStanislaw Gruszka return sign ? val : -val; 47*e87b5039SStanislaw Gruszka } 48*e87b5039SStanislaw Gruszka 49*e87b5039SStanislaw Gruszka static int 50*e87b5039SStanislaw Gruszka mt76x0_efuse_read(struct mt76x0_dev *dev, u16 addr, u8 *data, 51*e87b5039SStanislaw Gruszka enum mt76x0_eeprom_access_modes mode) 52*e87b5039SStanislaw Gruszka { 53*e87b5039SStanislaw Gruszka u32 val; 54*e87b5039SStanislaw Gruszka int i; 55*e87b5039SStanislaw Gruszka 56*e87b5039SStanislaw Gruszka val = mt76_rr(dev, MT_EFUSE_CTRL); 57*e87b5039SStanislaw Gruszka val &= ~(MT_EFUSE_CTRL_AIN | 58*e87b5039SStanislaw Gruszka MT_EFUSE_CTRL_MODE); 59*e87b5039SStanislaw Gruszka val |= FIELD_PREP(MT_EFUSE_CTRL_AIN, addr & ~0xf) | 60*e87b5039SStanislaw Gruszka FIELD_PREP(MT_EFUSE_CTRL_MODE, mode) | 61*e87b5039SStanislaw Gruszka MT_EFUSE_CTRL_KICK; 62*e87b5039SStanislaw Gruszka mt76_wr(dev, MT_EFUSE_CTRL, val); 63*e87b5039SStanislaw Gruszka 64*e87b5039SStanislaw Gruszka if (!mt76_poll(dev, MT_EFUSE_CTRL, MT_EFUSE_CTRL_KICK, 0, 1000)) 65*e87b5039SStanislaw Gruszka return -ETIMEDOUT; 66*e87b5039SStanislaw Gruszka 67*e87b5039SStanislaw Gruszka val = mt76_rr(dev, MT_EFUSE_CTRL); 68*e87b5039SStanislaw Gruszka if ((val & MT_EFUSE_CTRL_AOUT) == MT_EFUSE_CTRL_AOUT) { 69*e87b5039SStanislaw Gruszka /* Parts of eeprom not in the usage map (0x80-0xc0,0xf0) 70*e87b5039SStanislaw Gruszka * will not return valid data but it's ok. 71*e87b5039SStanislaw Gruszka */ 72*e87b5039SStanislaw Gruszka memset(data, 0xff, 16); 73*e87b5039SStanislaw Gruszka return 0; 74*e87b5039SStanislaw Gruszka } 75*e87b5039SStanislaw Gruszka 76*e87b5039SStanislaw Gruszka for (i = 0; i < 4; i++) { 77*e87b5039SStanislaw Gruszka val = mt76_rr(dev, MT_EFUSE_DATA(i)); 78*e87b5039SStanislaw Gruszka put_unaligned_le32(val, data + 4 * i); 79*e87b5039SStanislaw Gruszka } 80*e87b5039SStanislaw Gruszka 81*e87b5039SStanislaw Gruszka return 0; 82*e87b5039SStanislaw Gruszka } 83*e87b5039SStanislaw Gruszka 84*e87b5039SStanislaw Gruszka static int 85*e87b5039SStanislaw Gruszka mt76x0_efuse_physical_size_check(struct mt76x0_dev *dev) 86*e87b5039SStanislaw Gruszka { 87*e87b5039SStanislaw Gruszka const int map_reads = DIV_ROUND_UP(MT_EFUSE_USAGE_MAP_SIZE, 16); 88*e87b5039SStanislaw Gruszka u8 data[map_reads * 16]; 89*e87b5039SStanislaw Gruszka int ret, i; 90*e87b5039SStanislaw Gruszka u32 start = 0, end = 0, cnt_free; 91*e87b5039SStanislaw Gruszka 92*e87b5039SStanislaw Gruszka for (i = 0; i < map_reads; i++) { 93*e87b5039SStanislaw Gruszka ret = mt76x0_efuse_read(dev, MT_EE_USAGE_MAP_START + i * 16, 94*e87b5039SStanislaw Gruszka data + i * 16, MT_EE_PHYSICAL_READ); 95*e87b5039SStanislaw Gruszka if (ret) 96*e87b5039SStanislaw Gruszka return ret; 97*e87b5039SStanislaw Gruszka } 98*e87b5039SStanislaw Gruszka 99*e87b5039SStanislaw Gruszka for (i = 0; i < MT_EFUSE_USAGE_MAP_SIZE; i++) 100*e87b5039SStanislaw Gruszka if (!data[i]) { 101*e87b5039SStanislaw Gruszka if (!start) 102*e87b5039SStanislaw Gruszka start = MT_EE_USAGE_MAP_START + i; 103*e87b5039SStanislaw Gruszka end = MT_EE_USAGE_MAP_START + i; 104*e87b5039SStanislaw Gruszka } 105*e87b5039SStanislaw Gruszka cnt_free = end - start + 1; 106*e87b5039SStanislaw Gruszka 107*e87b5039SStanislaw Gruszka if (MT_EFUSE_USAGE_MAP_SIZE - cnt_free < 5) { 108*e87b5039SStanislaw Gruszka dev_err(dev->mt76.dev, "Error: your device needs default EEPROM file and this driver doesn't support it!\n"); 109*e87b5039SStanislaw Gruszka return -EINVAL; 110*e87b5039SStanislaw Gruszka } 111*e87b5039SStanislaw Gruszka 112*e87b5039SStanislaw Gruszka return 0; 113*e87b5039SStanislaw Gruszka } 114*e87b5039SStanislaw Gruszka 115*e87b5039SStanislaw Gruszka static void 116*e87b5039SStanislaw Gruszka mt76x0_set_chip_cap(struct mt76x0_dev *dev, u8 *eeprom) 117*e87b5039SStanislaw Gruszka { 118*e87b5039SStanislaw Gruszka enum mt76x2_board_type { BOARD_TYPE_2GHZ = 1, BOARD_TYPE_5GHZ = 2 }; 119*e87b5039SStanislaw Gruszka u16 nic_conf0 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_0); 120*e87b5039SStanislaw Gruszka u16 nic_conf1 = get_unaligned_le16(eeprom + MT_EE_NIC_CONF_1); 121*e87b5039SStanislaw Gruszka 122*e87b5039SStanislaw Gruszka dev_dbg(dev->mt76.dev, "NIC_CONF0: %04x NIC_CONF1: %04x\n", nic_conf0, nic_conf1); 123*e87b5039SStanislaw Gruszka 124*e87b5039SStanislaw Gruszka switch (FIELD_GET(MT_EE_NIC_CONF_0_BOARD_TYPE, nic_conf0)) { 125*e87b5039SStanislaw Gruszka case BOARD_TYPE_5GHZ: 126*e87b5039SStanislaw Gruszka dev->ee->has_5ghz = true; 127*e87b5039SStanislaw Gruszka break; 128*e87b5039SStanislaw Gruszka case BOARD_TYPE_2GHZ: 129*e87b5039SStanislaw Gruszka dev->ee->has_2ghz = true; 130*e87b5039SStanislaw Gruszka break; 131*e87b5039SStanislaw Gruszka default: 132*e87b5039SStanislaw Gruszka dev->ee->has_2ghz = true; 133*e87b5039SStanislaw Gruszka dev->ee->has_5ghz = true; 134*e87b5039SStanislaw Gruszka break; 135*e87b5039SStanislaw Gruszka } 136*e87b5039SStanislaw Gruszka 137*e87b5039SStanislaw Gruszka dev_dbg(dev->mt76.dev, "Has 2GHZ %d 5GHZ %d\n", dev->ee->has_2ghz, dev->ee->has_5ghz); 138*e87b5039SStanislaw Gruszka 139*e87b5039SStanislaw Gruszka if (!field_valid(nic_conf1 & 0xff)) 140*e87b5039SStanislaw Gruszka nic_conf1 &= 0xff00; 141*e87b5039SStanislaw Gruszka 142*e87b5039SStanislaw Gruszka if (nic_conf1 & MT_EE_NIC_CONF_1_HW_RF_CTRL) 143*e87b5039SStanislaw Gruszka dev_err(dev->mt76.dev, 144*e87b5039SStanislaw Gruszka "Error: this driver does not support HW RF ctrl\n"); 145*e87b5039SStanislaw Gruszka 146*e87b5039SStanislaw Gruszka if (!field_valid(nic_conf0 >> 8)) 147*e87b5039SStanislaw Gruszka return; 148*e87b5039SStanislaw Gruszka 149*e87b5039SStanislaw Gruszka if (FIELD_GET(MT_EE_NIC_CONF_0_RX_PATH, nic_conf0) > 1 || 150*e87b5039SStanislaw Gruszka FIELD_GET(MT_EE_NIC_CONF_0_TX_PATH, nic_conf0) > 1) 151*e87b5039SStanislaw Gruszka dev_err(dev->mt76.dev, 152*e87b5039SStanislaw Gruszka "Error: device has more than 1 RX/TX stream!\n"); 153*e87b5039SStanislaw Gruszka 154*e87b5039SStanislaw Gruszka dev->ee->pa_type = FIELD_GET(MT_EE_NIC_CONF_0_PA_TYPE, nic_conf0); 155*e87b5039SStanislaw Gruszka dev_dbg(dev->mt76.dev, "PA Type %d\n", dev->ee->pa_type); 156*e87b5039SStanislaw Gruszka } 157*e87b5039SStanislaw Gruszka 158*e87b5039SStanislaw Gruszka static int 159*e87b5039SStanislaw Gruszka mt76x0_set_macaddr(struct mt76x0_dev *dev, const u8 *eeprom) 160*e87b5039SStanislaw Gruszka { 161*e87b5039SStanislaw Gruszka const void *src = eeprom + MT_EE_MAC_ADDR; 162*e87b5039SStanislaw Gruszka 163*e87b5039SStanislaw Gruszka ether_addr_copy(dev->macaddr, src); 164*e87b5039SStanislaw Gruszka 165*e87b5039SStanislaw Gruszka if (!is_valid_ether_addr(dev->macaddr)) { 166*e87b5039SStanislaw Gruszka eth_random_addr(dev->macaddr); 167*e87b5039SStanislaw Gruszka dev_info(dev->mt76.dev, 168*e87b5039SStanislaw Gruszka "Invalid MAC address, using random address %pM\n", 169*e87b5039SStanislaw Gruszka dev->macaddr); 170*e87b5039SStanislaw Gruszka } 171*e87b5039SStanislaw Gruszka 172*e87b5039SStanislaw Gruszka mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(dev->macaddr)); 173*e87b5039SStanislaw Gruszka mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(dev->macaddr + 4) | 174*e87b5039SStanislaw Gruszka FIELD_PREP(MT_MAC_ADDR_DW1_U2ME_MASK, 0xff)); 175*e87b5039SStanislaw Gruszka 176*e87b5039SStanislaw Gruszka return 0; 177*e87b5039SStanislaw Gruszka } 178*e87b5039SStanislaw Gruszka 179*e87b5039SStanislaw Gruszka static void 180*e87b5039SStanislaw Gruszka mt76x0_set_temp_offset(struct mt76x0_dev *dev, u8 *eeprom) 181*e87b5039SStanislaw Gruszka { 182*e87b5039SStanislaw Gruszka u8 temp = eeprom[MT_EE_TEMP_OFFSET]; 183*e87b5039SStanislaw Gruszka 184*e87b5039SStanislaw Gruszka if (field_valid(temp)) 185*e87b5039SStanislaw Gruszka dev->ee->temp_off = sign_extend(temp, 8); 186*e87b5039SStanislaw Gruszka else 187*e87b5039SStanislaw Gruszka dev->ee->temp_off = -10; 188*e87b5039SStanislaw Gruszka } 189*e87b5039SStanislaw Gruszka 190*e87b5039SStanislaw Gruszka static void 191*e87b5039SStanislaw Gruszka mt76x0_set_country_reg(struct mt76x0_dev *dev, u8 *eeprom) 192*e87b5039SStanislaw Gruszka { 193*e87b5039SStanislaw Gruszka /* Note: - region 31 is not valid for mt76x0 (see rtmp_init.c) 194*e87b5039SStanislaw Gruszka * - comments in rtmp_def.h are incorrect (see rt_channel.c) 195*e87b5039SStanislaw Gruszka */ 196*e87b5039SStanislaw Gruszka static const struct reg_channel_bounds chan_bounds[] = { 197*e87b5039SStanislaw Gruszka /* EEPROM country regions 0 - 7 */ 198*e87b5039SStanislaw Gruszka { 1, 11 }, { 1, 13 }, { 10, 2 }, { 10, 4 }, 199*e87b5039SStanislaw Gruszka { 14, 1 }, { 1, 14 }, { 3, 7 }, { 5, 9 }, 200*e87b5039SStanislaw Gruszka /* EEPROM country regions 32 - 33 */ 201*e87b5039SStanislaw Gruszka { 1, 11 }, { 1, 14 } 202*e87b5039SStanislaw Gruszka }; 203*e87b5039SStanislaw Gruszka u8 val = eeprom[MT_EE_COUNTRY_REGION_2GHZ]; 204*e87b5039SStanislaw Gruszka int idx = -1; 205*e87b5039SStanislaw Gruszka 206*e87b5039SStanislaw Gruszka dev_dbg(dev->mt76.dev, "REG 2GHZ %u REG 5GHZ %u\n", val, eeprom[MT_EE_COUNTRY_REGION_5GHZ]); 207*e87b5039SStanislaw Gruszka if (val < 8) 208*e87b5039SStanislaw Gruszka idx = val; 209*e87b5039SStanislaw Gruszka if (val > 31 && val < 33) 210*e87b5039SStanislaw Gruszka idx = val - 32 + 8; 211*e87b5039SStanislaw Gruszka 212*e87b5039SStanislaw Gruszka if (idx != -1) 213*e87b5039SStanislaw Gruszka dev_info(dev->mt76.dev, 214*e87b5039SStanislaw Gruszka "EEPROM country region %02hhx (channels %hhd-%hhd)\n", 215*e87b5039SStanislaw Gruszka val, chan_bounds[idx].start, 216*e87b5039SStanislaw Gruszka chan_bounds[idx].start + chan_bounds[idx].num - 1); 217*e87b5039SStanislaw Gruszka else 218*e87b5039SStanislaw Gruszka idx = 5; /* channels 1 - 14 */ 219*e87b5039SStanislaw Gruszka 220*e87b5039SStanislaw Gruszka dev->ee->reg = chan_bounds[idx]; 221*e87b5039SStanislaw Gruszka 222*e87b5039SStanislaw Gruszka /* TODO: country region 33 is special - phy should be set to B-mode 223*e87b5039SStanislaw Gruszka * before entering channel 14 (see sta/connect.c) 224*e87b5039SStanislaw Gruszka */ 225*e87b5039SStanislaw Gruszka } 226*e87b5039SStanislaw Gruszka 227*e87b5039SStanislaw Gruszka static void 228*e87b5039SStanislaw Gruszka mt76x0_set_rf_freq_off(struct mt76x0_dev *dev, u8 *eeprom) 229*e87b5039SStanislaw Gruszka { 230*e87b5039SStanislaw Gruszka u8 comp; 231*e87b5039SStanislaw Gruszka 232*e87b5039SStanislaw Gruszka dev->ee->rf_freq_off = field_validate(eeprom[MT_EE_FREQ_OFFSET]); 233*e87b5039SStanislaw Gruszka comp = field_validate(eeprom[MT_EE_FREQ_OFFSET_COMPENSATION]); 234*e87b5039SStanislaw Gruszka 235*e87b5039SStanislaw Gruszka if (comp & BIT(7)) 236*e87b5039SStanislaw Gruszka dev->ee->rf_freq_off -= comp & 0x7f; 237*e87b5039SStanislaw Gruszka else 238*e87b5039SStanislaw Gruszka dev->ee->rf_freq_off += comp; 239*e87b5039SStanislaw Gruszka } 240*e87b5039SStanislaw Gruszka 241*e87b5039SStanislaw Gruszka static void 242*e87b5039SStanislaw Gruszka mt76x0_set_lna_gain(struct mt76x0_dev *dev, u8 *eeprom) 243*e87b5039SStanislaw Gruszka { 244*e87b5039SStanislaw Gruszka s8 gain; 245*e87b5039SStanislaw Gruszka 246*e87b5039SStanislaw Gruszka dev->ee->lna_gain_2ghz = eeprom[MT_EE_LNA_GAIN_2GHZ]; 247*e87b5039SStanislaw Gruszka dev->ee->lna_gain_5ghz[0] = eeprom[MT_EE_LNA_GAIN_5GHZ_0]; 248*e87b5039SStanislaw Gruszka 249*e87b5039SStanislaw Gruszka gain = eeprom[MT_EE_LNA_GAIN_5GHZ_1]; 250*e87b5039SStanislaw Gruszka if (gain == 0xff || gain == 0) 251*e87b5039SStanislaw Gruszka dev->ee->lna_gain_5ghz[1] = dev->ee->lna_gain_5ghz[0]; 252*e87b5039SStanislaw Gruszka else 253*e87b5039SStanislaw Gruszka dev->ee->lna_gain_5ghz[1] = gain; 254*e87b5039SStanislaw Gruszka 255*e87b5039SStanislaw Gruszka gain = eeprom[MT_EE_LNA_GAIN_5GHZ_2]; 256*e87b5039SStanislaw Gruszka if (gain == 0xff || gain == 0) 257*e87b5039SStanislaw Gruszka dev->ee->lna_gain_5ghz[2] = dev->ee->lna_gain_5ghz[0]; 258*e87b5039SStanislaw Gruszka else 259*e87b5039SStanislaw Gruszka dev->ee->lna_gain_5ghz[2] = gain; 260*e87b5039SStanislaw Gruszka } 261*e87b5039SStanislaw Gruszka 262*e87b5039SStanislaw Gruszka static void 263*e87b5039SStanislaw Gruszka mt76x0_set_rssi_offset(struct mt76x0_dev *dev, u8 *eeprom) 264*e87b5039SStanislaw Gruszka { 265*e87b5039SStanislaw Gruszka int i; 266*e87b5039SStanislaw Gruszka s8 *rssi_offset = dev->ee->rssi_offset_2ghz; 267*e87b5039SStanislaw Gruszka 268*e87b5039SStanislaw Gruszka for (i = 0; i < 2; i++) { 269*e87b5039SStanislaw Gruszka rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET + i]; 270*e87b5039SStanislaw Gruszka 271*e87b5039SStanislaw Gruszka if (rssi_offset[i] < -10 || rssi_offset[i] > 10) { 272*e87b5039SStanislaw Gruszka dev_warn(dev->mt76.dev, 273*e87b5039SStanislaw Gruszka "Warning: EEPROM RSSI is invalid %02hhx\n", 274*e87b5039SStanislaw Gruszka rssi_offset[i]); 275*e87b5039SStanislaw Gruszka rssi_offset[i] = 0; 276*e87b5039SStanislaw Gruszka } 277*e87b5039SStanislaw Gruszka } 278*e87b5039SStanislaw Gruszka 279*e87b5039SStanislaw Gruszka rssi_offset = dev->ee->rssi_offset_5ghz; 280*e87b5039SStanislaw Gruszka 281*e87b5039SStanislaw Gruszka for (i = 0; i < 3; i++) { 282*e87b5039SStanislaw Gruszka rssi_offset[i] = eeprom[MT_EE_RSSI_OFFSET_5GHZ + i]; 283*e87b5039SStanislaw Gruszka 284*e87b5039SStanislaw Gruszka if (rssi_offset[i] < -10 || rssi_offset[i] > 10) { 285*e87b5039SStanislaw Gruszka dev_warn(dev->mt76.dev, 286*e87b5039SStanislaw Gruszka "Warning: EEPROM RSSI is invalid %02hhx\n", 287*e87b5039SStanislaw Gruszka rssi_offset[i]); 288*e87b5039SStanislaw Gruszka rssi_offset[i] = 0; 289*e87b5039SStanislaw Gruszka } 290*e87b5039SStanislaw Gruszka } 291*e87b5039SStanislaw Gruszka } 292*e87b5039SStanislaw Gruszka 293*e87b5039SStanislaw Gruszka static u32 294*e87b5039SStanislaw Gruszka calc_bw40_power_rate(u32 value, int delta) 295*e87b5039SStanislaw Gruszka { 296*e87b5039SStanislaw Gruszka u32 ret = 0; 297*e87b5039SStanislaw Gruszka int i, tmp; 298*e87b5039SStanislaw Gruszka 299*e87b5039SStanislaw Gruszka for (i = 0; i < 4; i++) { 300*e87b5039SStanislaw Gruszka tmp = s6_to_int((value >> i*8) & 0xff) + delta; 301*e87b5039SStanislaw Gruszka ret |= (u32)(int_to_s6(tmp)) << i*8; 302*e87b5039SStanislaw Gruszka } 303*e87b5039SStanislaw Gruszka 304*e87b5039SStanislaw Gruszka return ret; 305*e87b5039SStanislaw Gruszka } 306*e87b5039SStanislaw Gruszka 307*e87b5039SStanislaw Gruszka static s8 308*e87b5039SStanislaw Gruszka get_delta(u8 val) 309*e87b5039SStanislaw Gruszka { 310*e87b5039SStanislaw Gruszka s8 ret; 311*e87b5039SStanislaw Gruszka 312*e87b5039SStanislaw Gruszka if (!field_valid(val) || !(val & BIT(7))) 313*e87b5039SStanislaw Gruszka return 0; 314*e87b5039SStanislaw Gruszka 315*e87b5039SStanislaw Gruszka ret = val & 0x1f; 316*e87b5039SStanislaw Gruszka if (ret > 8) 317*e87b5039SStanislaw Gruszka ret = 8; 318*e87b5039SStanislaw Gruszka if (val & BIT(6)) 319*e87b5039SStanislaw Gruszka ret = -ret; 320*e87b5039SStanislaw Gruszka 321*e87b5039SStanislaw Gruszka return ret; 322*e87b5039SStanislaw Gruszka } 323*e87b5039SStanislaw Gruszka 324*e87b5039SStanislaw Gruszka static void 325*e87b5039SStanislaw Gruszka mt76x0_set_tx_power_per_rate(struct mt76x0_dev *dev, u8 *eeprom) 326*e87b5039SStanislaw Gruszka { 327*e87b5039SStanislaw Gruszka s8 bw40_delta_2g, bw40_delta_5g; 328*e87b5039SStanislaw Gruszka u32 val; 329*e87b5039SStanislaw Gruszka int i; 330*e87b5039SStanislaw Gruszka 331*e87b5039SStanislaw Gruszka bw40_delta_2g = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40]); 332*e87b5039SStanislaw Gruszka bw40_delta_5g = get_delta(eeprom[MT_EE_TX_POWER_DELTA_BW40 + 1]); 333*e87b5039SStanislaw Gruszka 334*e87b5039SStanislaw Gruszka for (i = 0; i < 5; i++) { 335*e87b5039SStanislaw Gruszka val = get_unaligned_le32(eeprom + MT_EE_TX_POWER_BYRATE(i)); 336*e87b5039SStanislaw Gruszka 337*e87b5039SStanislaw Gruszka /* Skip last 16 bits. */ 338*e87b5039SStanislaw Gruszka if (i == 4) 339*e87b5039SStanislaw Gruszka val &= 0x0000ffff; 340*e87b5039SStanislaw Gruszka 341*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_2g[i][0] = val; 342*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_2g[i][1] = calc_bw40_power_rate(val, bw40_delta_2g); 343*e87b5039SStanislaw Gruszka } 344*e87b5039SStanislaw Gruszka 345*e87b5039SStanislaw Gruszka /* Reading per rate tx power for 5 GHz band is a bit more complex. Note 346*e87b5039SStanislaw Gruszka * we mix 16 bit and 32 bit reads and sometimes do shifts. 347*e87b5039SStanislaw Gruszka */ 348*e87b5039SStanislaw Gruszka val = get_unaligned_le16(eeprom + 0x120); 349*e87b5039SStanislaw Gruszka val <<= 16; 350*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[0][0] = val; 351*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[0][1] = calc_bw40_power_rate(val, bw40_delta_5g); 352*e87b5039SStanislaw Gruszka 353*e87b5039SStanislaw Gruszka val = get_unaligned_le32(eeprom + 0x122); 354*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[1][0] = val; 355*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[1][1] = calc_bw40_power_rate(val, bw40_delta_5g); 356*e87b5039SStanislaw Gruszka 357*e87b5039SStanislaw Gruszka val = get_unaligned_le16(eeprom + 0x126); 358*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[2][0] = val; 359*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[2][1] = calc_bw40_power_rate(val, bw40_delta_5g); 360*e87b5039SStanislaw Gruszka 361*e87b5039SStanislaw Gruszka val = get_unaligned_le16(eeprom + 0xec); 362*e87b5039SStanislaw Gruszka val <<= 16; 363*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[3][0] = val; 364*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[3][1] = calc_bw40_power_rate(val, bw40_delta_5g); 365*e87b5039SStanislaw Gruszka 366*e87b5039SStanislaw Gruszka val = get_unaligned_le16(eeprom + 0xee); 367*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[4][0] = val; 368*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_cfg_5g[4][1] = calc_bw40_power_rate(val, bw40_delta_5g); 369*e87b5039SStanislaw Gruszka } 370*e87b5039SStanislaw Gruszka 371*e87b5039SStanislaw Gruszka static void 372*e87b5039SStanislaw Gruszka mt76x0_set_tx_power_per_chan(struct mt76x0_dev *dev, u8 *eeprom) 373*e87b5039SStanislaw Gruszka { 374*e87b5039SStanislaw Gruszka int i; 375*e87b5039SStanislaw Gruszka u8 tx_pwr; 376*e87b5039SStanislaw Gruszka 377*e87b5039SStanislaw Gruszka for (i = 0; i < 14; i++) { 378*e87b5039SStanislaw Gruszka tx_pwr = eeprom[MT_EE_TX_POWER_OFFSET_2GHZ + i]; 379*e87b5039SStanislaw Gruszka if (tx_pwr <= 0x3f && tx_pwr > 0) 380*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[i] = tx_pwr; 381*e87b5039SStanislaw Gruszka else 382*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[i] = 5; 383*e87b5039SStanislaw Gruszka } 384*e87b5039SStanislaw Gruszka 385*e87b5039SStanislaw Gruszka for (i = 0; i < 40; i++) { 386*e87b5039SStanislaw Gruszka tx_pwr = eeprom[MT_EE_TX_POWER_OFFSET_5GHZ + i]; 387*e87b5039SStanislaw Gruszka if (tx_pwr <= 0x3f && tx_pwr > 0) 388*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[14 + i] = tx_pwr; 389*e87b5039SStanislaw Gruszka else 390*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[14 + i] = 5; 391*e87b5039SStanislaw Gruszka } 392*e87b5039SStanislaw Gruszka 393*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[54] = dev->ee->tx_pwr_per_chan[22]; 394*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[55] = dev->ee->tx_pwr_per_chan[28]; 395*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[56] = dev->ee->tx_pwr_per_chan[34]; 396*e87b5039SStanislaw Gruszka dev->ee->tx_pwr_per_chan[57] = dev->ee->tx_pwr_per_chan[44]; 397*e87b5039SStanislaw Gruszka } 398*e87b5039SStanislaw Gruszka 399*e87b5039SStanislaw Gruszka int 400*e87b5039SStanislaw Gruszka mt76x0_eeprom_init(struct mt76x0_dev *dev) 401*e87b5039SStanislaw Gruszka { 402*e87b5039SStanislaw Gruszka u8 *eeprom; 403*e87b5039SStanislaw Gruszka int i, ret; 404*e87b5039SStanislaw Gruszka 405*e87b5039SStanislaw Gruszka ret = mt76x0_efuse_physical_size_check(dev); 406*e87b5039SStanislaw Gruszka if (ret) 407*e87b5039SStanislaw Gruszka return ret; 408*e87b5039SStanislaw Gruszka 409*e87b5039SStanislaw Gruszka dev->ee = devm_kzalloc(dev->mt76.dev, sizeof(*dev->ee), GFP_KERNEL); 410*e87b5039SStanislaw Gruszka if (!dev->ee) 411*e87b5039SStanislaw Gruszka return -ENOMEM; 412*e87b5039SStanislaw Gruszka 413*e87b5039SStanislaw Gruszka eeprom = kmalloc(MT76X0_EEPROM_SIZE, GFP_KERNEL); 414*e87b5039SStanislaw Gruszka if (!eeprom) 415*e87b5039SStanislaw Gruszka return -ENOMEM; 416*e87b5039SStanislaw Gruszka 417*e87b5039SStanislaw Gruszka for (i = 0; i + 16 <= MT76X0_EEPROM_SIZE; i += 16) { 418*e87b5039SStanislaw Gruszka ret = mt76x0_efuse_read(dev, i, eeprom + i, MT_EE_READ); 419*e87b5039SStanislaw Gruszka if (ret) 420*e87b5039SStanislaw Gruszka goto out; 421*e87b5039SStanislaw Gruszka } 422*e87b5039SStanislaw Gruszka 423*e87b5039SStanislaw Gruszka if (eeprom[MT_EE_VERSION_EE] > MT76X0U_EE_MAX_VER) 424*e87b5039SStanislaw Gruszka dev_warn(dev->mt76.dev, 425*e87b5039SStanislaw Gruszka "Warning: unsupported EEPROM version %02hhx\n", 426*e87b5039SStanislaw Gruszka eeprom[MT_EE_VERSION_EE]); 427*e87b5039SStanislaw Gruszka dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n", 428*e87b5039SStanislaw Gruszka eeprom[MT_EE_VERSION_EE], eeprom[MT_EE_VERSION_FAE]); 429*e87b5039SStanislaw Gruszka 430*e87b5039SStanislaw Gruszka mt76x0_set_macaddr(dev, eeprom); 431*e87b5039SStanislaw Gruszka mt76x0_set_chip_cap(dev, eeprom); 432*e87b5039SStanislaw Gruszka mt76x0_set_country_reg(dev, eeprom); 433*e87b5039SStanislaw Gruszka mt76x0_set_rf_freq_off(dev, eeprom); 434*e87b5039SStanislaw Gruszka mt76x0_set_temp_offset(dev, eeprom); 435*e87b5039SStanislaw Gruszka mt76x0_set_lna_gain(dev, eeprom); 436*e87b5039SStanislaw Gruszka mt76x0_set_rssi_offset(dev, eeprom); 437*e87b5039SStanislaw Gruszka dev->chainmask = 0x0101; 438*e87b5039SStanislaw Gruszka 439*e87b5039SStanislaw Gruszka mt76x0_set_tx_power_per_rate(dev, eeprom); 440*e87b5039SStanislaw Gruszka mt76x0_set_tx_power_per_chan(dev, eeprom); 441*e87b5039SStanislaw Gruszka 442*e87b5039SStanislaw Gruszka out: 443*e87b5039SStanislaw Gruszka kfree(eeprom); 444*e87b5039SStanislaw Gruszka return ret; 445*e87b5039SStanislaw Gruszka } 446