1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2018 Intel Corporation */ 3 4 #include "igc_mac.h" 5 #include "igc_nvm.h" 6 7 /** 8 * igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion 9 * @hw: pointer to the HW structure 10 * @ee_reg: EEPROM flag for polling 11 * 12 * Polls the EEPROM status bit for either read or write completion based 13 * upon the value of 'ee_reg'. 14 */ 15 static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg) 16 { 17 s32 ret_val = -IGC_ERR_NVM; 18 u32 attempts = 100000; 19 u32 i, reg = 0; 20 21 for (i = 0; i < attempts; i++) { 22 if (ee_reg == IGC_NVM_POLL_READ) 23 reg = rd32(IGC_EERD); 24 else 25 reg = rd32(IGC_EEWR); 26 27 if (reg & IGC_NVM_RW_REG_DONE) { 28 ret_val = 0; 29 break; 30 } 31 32 udelay(5); 33 } 34 35 return ret_val; 36 } 37 38 /** 39 * igc_acquire_nvm - Generic request for access to EEPROM 40 * @hw: pointer to the HW structure 41 * 42 * Set the EEPROM access request bit and wait for EEPROM access grant bit. 43 * Return successful if access grant bit set, else clear the request for 44 * EEPROM access and return -IGC_ERR_NVM (-1). 45 */ 46 s32 igc_acquire_nvm(struct igc_hw *hw) 47 { 48 s32 timeout = IGC_NVM_GRANT_ATTEMPTS; 49 u32 eecd = rd32(IGC_EECD); 50 s32 ret_val = 0; 51 52 wr32(IGC_EECD, eecd | IGC_EECD_REQ); 53 eecd = rd32(IGC_EECD); 54 55 while (timeout) { 56 if (eecd & IGC_EECD_GNT) 57 break; 58 udelay(5); 59 eecd = rd32(IGC_EECD); 60 timeout--; 61 } 62 63 if (!timeout) { 64 eecd &= ~IGC_EECD_REQ; 65 wr32(IGC_EECD, eecd); 66 hw_dbg("Could not acquire NVM grant\n"); 67 ret_val = -IGC_ERR_NVM; 68 } 69 70 return ret_val; 71 } 72 73 /** 74 * igc_release_nvm - Release exclusive access to EEPROM 75 * @hw: pointer to the HW structure 76 * 77 * Stop any current commands to the EEPROM and clear the EEPROM request bit. 78 */ 79 void igc_release_nvm(struct igc_hw *hw) 80 { 81 u32 eecd; 82 83 eecd = rd32(IGC_EECD); 84 eecd &= ~IGC_EECD_REQ; 85 wr32(IGC_EECD, eecd); 86 } 87 88 /** 89 * igc_read_nvm_eerd - Reads EEPROM using EERD register 90 * @hw: pointer to the HW structure 91 * @offset: offset of word in the EEPROM to read 92 * @words: number of words to read 93 * @data: word read from the EEPROM 94 * 95 * Reads a 16 bit word from the EEPROM using the EERD register. 96 */ 97 s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data) 98 { 99 struct igc_nvm_info *nvm = &hw->nvm; 100 u32 i, eerd = 0; 101 s32 ret_val = 0; 102 103 /* A check for invalid values: offset too large, too many words, 104 * and not enough words. 105 */ 106 if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || 107 words == 0) { 108 hw_dbg("nvm parameter(s) out of bounds\n"); 109 ret_val = -IGC_ERR_NVM; 110 goto out; 111 } 112 113 for (i = 0; i < words; i++) { 114 eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) + 115 IGC_NVM_RW_REG_START; 116 117 wr32(IGC_EERD, eerd); 118 ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ); 119 if (ret_val) 120 break; 121 122 data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA); 123 } 124 125 out: 126 return ret_val; 127 } 128 129 /** 130 * igc_read_mac_addr - Read device MAC address 131 * @hw: pointer to the HW structure 132 */ 133 s32 igc_read_mac_addr(struct igc_hw *hw) 134 { 135 u32 rar_high; 136 u32 rar_low; 137 u16 i; 138 139 rar_high = rd32(IGC_RAH(0)); 140 rar_low = rd32(IGC_RAL(0)); 141 142 for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++) 143 hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); 144 145 for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++) 146 hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); 147 148 for (i = 0; i < ETH_ALEN; i++) 149 hw->mac.addr[i] = hw->mac.perm_addr[i]; 150 151 return 0; 152 } 153 154 /** 155 * igc_validate_nvm_checksum - Validate EEPROM checksum 156 * @hw: pointer to the HW structure 157 * 158 * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 159 * and then verifies that the sum of the EEPROM is equal to 0xBABA. 160 */ 161 s32 igc_validate_nvm_checksum(struct igc_hw *hw) 162 { 163 u16 checksum = 0; 164 u16 i, nvm_data; 165 s32 ret_val = 0; 166 167 for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { 168 ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 169 if (ret_val) { 170 hw_dbg("NVM Read Error\n"); 171 goto out; 172 } 173 checksum += nvm_data; 174 } 175 176 if (checksum != (u16)NVM_SUM) { 177 hw_dbg("NVM Checksum Invalid\n"); 178 ret_val = -IGC_ERR_NVM; 179 goto out; 180 } 181 182 out: 183 return ret_val; 184 } 185 186 /** 187 * igc_update_nvm_checksum - Update EEPROM checksum 188 * @hw: pointer to the HW structure 189 * 190 * Updates the EEPROM checksum by reading/adding each word of the EEPROM 191 * up to the checksum. Then calculates the EEPROM checksum and writes the 192 * value to the EEPROM. 193 */ 194 s32 igc_update_nvm_checksum(struct igc_hw *hw) 195 { 196 u16 checksum = 0; 197 u16 i, nvm_data; 198 s32 ret_val; 199 200 for (i = 0; i < NVM_CHECKSUM_REG; i++) { 201 ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 202 if (ret_val) { 203 hw_dbg("NVM Read Error while updating checksum.\n"); 204 goto out; 205 } 206 checksum += nvm_data; 207 } 208 checksum = (u16)NVM_SUM - checksum; 209 ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); 210 if (ret_val) 211 hw_dbg("NVM Write Error while updating checksum.\n"); 212 213 out: 214 return ret_val; 215 } 216