0001
0002
0003
0004 #include "igc_mac.h"
0005 #include "igc_nvm.h"
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
0016 {
0017 s32 ret_val = -IGC_ERR_NVM;
0018 u32 attempts = 100000;
0019 u32 i, reg = 0;
0020
0021 for (i = 0; i < attempts; i++) {
0022 if (ee_reg == IGC_NVM_POLL_READ)
0023 reg = rd32(IGC_EERD);
0024 else
0025 reg = rd32(IGC_EEWR);
0026
0027 if (reg & IGC_NVM_RW_REG_DONE) {
0028 ret_val = 0;
0029 break;
0030 }
0031
0032 udelay(5);
0033 }
0034
0035 return ret_val;
0036 }
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 s32 igc_acquire_nvm(struct igc_hw *hw)
0047 {
0048 s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
0049 u32 eecd = rd32(IGC_EECD);
0050 s32 ret_val = 0;
0051
0052 wr32(IGC_EECD, eecd | IGC_EECD_REQ);
0053 eecd = rd32(IGC_EECD);
0054
0055 while (timeout) {
0056 if (eecd & IGC_EECD_GNT)
0057 break;
0058 udelay(5);
0059 eecd = rd32(IGC_EECD);
0060 timeout--;
0061 }
0062
0063 if (!timeout) {
0064 eecd &= ~IGC_EECD_REQ;
0065 wr32(IGC_EECD, eecd);
0066 hw_dbg("Could not acquire NVM grant\n");
0067 ret_val = -IGC_ERR_NVM;
0068 }
0069
0070 return ret_val;
0071 }
0072
0073
0074
0075
0076
0077
0078
0079 void igc_release_nvm(struct igc_hw *hw)
0080 {
0081 u32 eecd;
0082
0083 eecd = rd32(IGC_EECD);
0084 eecd &= ~IGC_EECD_REQ;
0085 wr32(IGC_EECD, eecd);
0086 }
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
0098 {
0099 struct igc_nvm_info *nvm = &hw->nvm;
0100 u32 i, eerd = 0;
0101 s32 ret_val = 0;
0102
0103
0104
0105
0106 if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) ||
0107 words == 0) {
0108 hw_dbg("nvm parameter(s) out of bounds\n");
0109 ret_val = -IGC_ERR_NVM;
0110 goto out;
0111 }
0112
0113 for (i = 0; i < words; i++) {
0114 eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
0115 IGC_NVM_RW_REG_START;
0116
0117 wr32(IGC_EERD, eerd);
0118 ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
0119 if (ret_val)
0120 break;
0121
0122 data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA);
0123 }
0124
0125 out:
0126 return ret_val;
0127 }
0128
0129
0130
0131
0132
0133 s32 igc_read_mac_addr(struct igc_hw *hw)
0134 {
0135 u32 rar_high;
0136 u32 rar_low;
0137 u16 i;
0138
0139 rar_high = rd32(IGC_RAH(0));
0140 rar_low = rd32(IGC_RAL(0));
0141
0142 for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
0143 hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
0144
0145 for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
0146 hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
0147
0148 for (i = 0; i < ETH_ALEN; i++)
0149 hw->mac.addr[i] = hw->mac.perm_addr[i];
0150
0151 return 0;
0152 }
0153
0154
0155
0156
0157
0158
0159
0160
0161 s32 igc_validate_nvm_checksum(struct igc_hw *hw)
0162 {
0163 u16 checksum = 0;
0164 u16 i, nvm_data;
0165 s32 ret_val = 0;
0166
0167 for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
0168 ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
0169 if (ret_val) {
0170 hw_dbg("NVM Read Error\n");
0171 goto out;
0172 }
0173 checksum += nvm_data;
0174 }
0175
0176 if (checksum != (u16)NVM_SUM) {
0177 hw_dbg("NVM Checksum Invalid\n");
0178 ret_val = -IGC_ERR_NVM;
0179 goto out;
0180 }
0181
0182 out:
0183 return ret_val;
0184 }
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194 s32 igc_update_nvm_checksum(struct igc_hw *hw)
0195 {
0196 u16 checksum = 0;
0197 u16 i, nvm_data;
0198 s32 ret_val;
0199
0200 for (i = 0; i < NVM_CHECKSUM_REG; i++) {
0201 ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
0202 if (ret_val) {
0203 hw_dbg("NVM Read Error while updating checksum.\n");
0204 goto out;
0205 }
0206 checksum += nvm_data;
0207 }
0208 checksum = (u16)NVM_SUM - checksum;
0209 ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
0210 if (ret_val)
0211 hw_dbg("NVM Write Error while updating checksum.\n");
0212
0213 out:
0214 return ret_val;
0215 }