dpdk/drivers/net/igc/base/igc_nvm.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2001-2020 Intel Corporation
   3 */
   4
   5#include "igc_api.h"
   6
   7static void igc_reload_nvm_generic(struct igc_hw *hw);
   8
   9/**
  10 *  igc_init_nvm_ops_generic - Initialize NVM function pointers
  11 *  @hw: pointer to the HW structure
  12 *
  13 *  Setups up the function pointers to no-op functions
  14 **/
  15void igc_init_nvm_ops_generic(struct igc_hw *hw)
  16{
  17        struct igc_nvm_info *nvm = &hw->nvm;
  18        DEBUGFUNC("igc_init_nvm_ops_generic");
  19
  20        /* Initialize function pointers */
  21        nvm->ops.init_params = igc_null_ops_generic;
  22        nvm->ops.acquire = igc_null_ops_generic;
  23        nvm->ops.read = igc_null_read_nvm;
  24        nvm->ops.release = igc_null_nvm_generic;
  25        nvm->ops.reload = igc_reload_nvm_generic;
  26        nvm->ops.update = igc_null_ops_generic;
  27        nvm->ops.valid_led_default = igc_null_led_default;
  28        nvm->ops.validate = igc_null_ops_generic;
  29        nvm->ops.write = igc_null_write_nvm;
  30}
  31
  32/**
  33 *  igc_null_nvm_read - No-op function, return 0
  34 *  @hw: pointer to the HW structure
  35 *  @a: dummy variable
  36 *  @b: dummy variable
  37 *  @c: dummy variable
  38 **/
  39s32 igc_null_read_nvm(struct igc_hw IGC_UNUSEDARG * hw,
  40                        u16 IGC_UNUSEDARG a, u16 IGC_UNUSEDARG b,
  41                        u16 IGC_UNUSEDARG * c)
  42{
  43        DEBUGFUNC("igc_null_read_nvm");
  44        UNREFERENCED_4PARAMETER(hw, a, b, c);
  45        return IGC_SUCCESS;
  46}
  47
  48/**
  49 *  igc_null_nvm_generic - No-op function, return void
  50 *  @hw: pointer to the HW structure
  51 **/
  52void igc_null_nvm_generic(struct igc_hw IGC_UNUSEDARG * hw)
  53{
  54        DEBUGFUNC("igc_null_nvm_generic");
  55        UNREFERENCED_1PARAMETER(hw);
  56}
  57
  58/**
  59 *  igc_null_led_default - No-op function, return 0
  60 *  @hw: pointer to the HW structure
  61 *  @data: dummy variable
  62 **/
  63s32 igc_null_led_default(struct igc_hw IGC_UNUSEDARG * hw,
  64                           u16 IGC_UNUSEDARG * data)
  65{
  66        DEBUGFUNC("igc_null_led_default");
  67        UNREFERENCED_2PARAMETER(hw, data);
  68        return IGC_SUCCESS;
  69}
  70
  71/**
  72 *  igc_null_write_nvm - No-op function, return 0
  73 *  @hw: pointer to the HW structure
  74 *  @a: dummy variable
  75 *  @b: dummy variable
  76 *  @c: dummy variable
  77 **/
  78s32 igc_null_write_nvm(struct igc_hw IGC_UNUSEDARG * hw,
  79                         u16 IGC_UNUSEDARG a, u16 IGC_UNUSEDARG b,
  80                         u16 IGC_UNUSEDARG * c)
  81{
  82        DEBUGFUNC("igc_null_write_nvm");
  83        UNREFERENCED_4PARAMETER(hw, a, b, c);
  84        return IGC_SUCCESS;
  85}
  86
  87/**
  88 *  igc_raise_eec_clk - Raise EEPROM clock
  89 *  @hw: pointer to the HW structure
  90 *  @eecd: pointer to the EEPROM
  91 *
  92 *  Enable/Raise the EEPROM clock bit.
  93 **/
  94static void igc_raise_eec_clk(struct igc_hw *hw, u32 *eecd)
  95{
  96        *eecd = *eecd | IGC_EECD_SK;
  97        IGC_WRITE_REG(hw, IGC_EECD, *eecd);
  98        IGC_WRITE_FLUSH(hw);
  99        usec_delay(hw->nvm.delay_usec);
 100}
 101
 102/**
 103 *  igc_lower_eec_clk - Lower EEPROM clock
 104 *  @hw: pointer to the HW structure
 105 *  @eecd: pointer to the EEPROM
 106 *
 107 *  Clear/Lower the EEPROM clock bit.
 108 **/
 109static void igc_lower_eec_clk(struct igc_hw *hw, u32 *eecd)
 110{
 111        *eecd = *eecd & ~IGC_EECD_SK;
 112        IGC_WRITE_REG(hw, IGC_EECD, *eecd);
 113        IGC_WRITE_FLUSH(hw);
 114        usec_delay(hw->nvm.delay_usec);
 115}
 116
 117/**
 118 *  igc_shift_out_eec_bits - Shift data bits our to the EEPROM
 119 *  @hw: pointer to the HW structure
 120 *  @data: data to send to the EEPROM
 121 *  @count: number of bits to shift out
 122 *
 123 *  We need to shift 'count' bits out to the EEPROM.  So, the value in the
 124 *  "data" parameter will be shifted out to the EEPROM one bit at a time.
 125 *  In order to do this, "data" must be broken down into bits.
 126 **/
 127static void igc_shift_out_eec_bits(struct igc_hw *hw, u16 data, u16 count)
 128{
 129        struct igc_nvm_info *nvm = &hw->nvm;
 130        u32 eecd = IGC_READ_REG(hw, IGC_EECD);
 131        u32 mask;
 132
 133        DEBUGFUNC("igc_shift_out_eec_bits");
 134
 135        mask = 0x01 << (count - 1);
 136        if (nvm->type == igc_nvm_eeprom_microwire)
 137                eecd &= ~IGC_EECD_DO;
 138        else if (nvm->type == igc_nvm_eeprom_spi)
 139                eecd |= IGC_EECD_DO;
 140
 141        do {
 142                eecd &= ~IGC_EECD_DI;
 143
 144                if (data & mask)
 145                        eecd |= IGC_EECD_DI;
 146
 147                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 148                IGC_WRITE_FLUSH(hw);
 149
 150                usec_delay(nvm->delay_usec);
 151
 152                igc_raise_eec_clk(hw, &eecd);
 153                igc_lower_eec_clk(hw, &eecd);
 154
 155                mask >>= 1;
 156        } while (mask);
 157
 158        eecd &= ~IGC_EECD_DI;
 159        IGC_WRITE_REG(hw, IGC_EECD, eecd);
 160}
 161
 162/**
 163 *  igc_shift_in_eec_bits - Shift data bits in from the EEPROM
 164 *  @hw: pointer to the HW structure
 165 *  @count: number of bits to shift in
 166 *
 167 *  In order to read a register from the EEPROM, we need to shift 'count' bits
 168 *  in from the EEPROM.  Bits are "shifted in" by raising the clock input to
 169 *  the EEPROM (setting the SK bit), and then reading the value of the data out
 170 *  "DO" bit.  During this "shifting in" process the data in "DI" bit should
 171 *  always be clear.
 172 **/
 173static u16 igc_shift_in_eec_bits(struct igc_hw *hw, u16 count)
 174{
 175        u32 eecd;
 176        u32 i;
 177        u16 data;
 178
 179        DEBUGFUNC("igc_shift_in_eec_bits");
 180
 181        eecd = IGC_READ_REG(hw, IGC_EECD);
 182
 183        eecd &= ~(IGC_EECD_DO | IGC_EECD_DI);
 184        data = 0;
 185
 186        for (i = 0; i < count; i++) {
 187                data <<= 1;
 188                igc_raise_eec_clk(hw, &eecd);
 189
 190                eecd = IGC_READ_REG(hw, IGC_EECD);
 191
 192                eecd &= ~IGC_EECD_DI;
 193                if (eecd & IGC_EECD_DO)
 194                        data |= 1;
 195
 196                igc_lower_eec_clk(hw, &eecd);
 197        }
 198
 199        return data;
 200}
 201
 202/**
 203 *  igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
 204 *  @hw: pointer to the HW structure
 205 *  @ee_reg: EEPROM flag for polling
 206 *
 207 *  Polls the EEPROM status bit for either read or write completion based
 208 *  upon the value of 'ee_reg'.
 209 **/
 210s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
 211{
 212        u32 attempts = 100000;
 213        u32 i, reg = 0;
 214
 215        DEBUGFUNC("igc_poll_eerd_eewr_done");
 216
 217        for (i = 0; i < attempts; i++) {
 218                if (ee_reg == IGC_NVM_POLL_READ)
 219                        reg = IGC_READ_REG(hw, IGC_EERD);
 220                else
 221                        reg = IGC_READ_REG(hw, IGC_EEWR);
 222
 223                if (reg & IGC_NVM_RW_REG_DONE)
 224                        return IGC_SUCCESS;
 225
 226                usec_delay(5);
 227        }
 228
 229        return -IGC_ERR_NVM;
 230}
 231
 232/**
 233 *  igc_acquire_nvm_generic - Generic request for access to EEPROM
 234 *  @hw: pointer to the HW structure
 235 *
 236 *  Set the EEPROM access request bit and wait for EEPROM access grant bit.
 237 *  Return successful if access grant bit set, else clear the request for
 238 *  EEPROM access and return -IGC_ERR_NVM (-1).
 239 **/
 240s32 igc_acquire_nvm_generic(struct igc_hw *hw)
 241{
 242        u32 eecd = IGC_READ_REG(hw, IGC_EECD);
 243        s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
 244
 245        DEBUGFUNC("igc_acquire_nvm_generic");
 246
 247        IGC_WRITE_REG(hw, IGC_EECD, eecd | IGC_EECD_REQ);
 248        eecd = IGC_READ_REG(hw, IGC_EECD);
 249
 250        while (timeout) {
 251                if (eecd & IGC_EECD_GNT)
 252                        break;
 253                usec_delay(5);
 254                eecd = IGC_READ_REG(hw, IGC_EECD);
 255                timeout--;
 256        }
 257
 258        if (!timeout) {
 259                eecd &= ~IGC_EECD_REQ;
 260                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 261                DEBUGOUT("Could not acquire NVM grant\n");
 262                return -IGC_ERR_NVM;
 263        }
 264
 265        return IGC_SUCCESS;
 266}
 267
 268/**
 269 *  igc_standby_nvm - Return EEPROM to standby state
 270 *  @hw: pointer to the HW structure
 271 *
 272 *  Return the EEPROM to a standby state.
 273 **/
 274static void igc_standby_nvm(struct igc_hw *hw)
 275{
 276        struct igc_nvm_info *nvm = &hw->nvm;
 277        u32 eecd = IGC_READ_REG(hw, IGC_EECD);
 278
 279        DEBUGFUNC("igc_standby_nvm");
 280
 281        if (nvm->type == igc_nvm_eeprom_microwire) {
 282                eecd &= ~(IGC_EECD_CS | IGC_EECD_SK);
 283                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 284                IGC_WRITE_FLUSH(hw);
 285                usec_delay(nvm->delay_usec);
 286
 287                igc_raise_eec_clk(hw, &eecd);
 288
 289                /* Select EEPROM */
 290                eecd |= IGC_EECD_CS;
 291                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 292                IGC_WRITE_FLUSH(hw);
 293                usec_delay(nvm->delay_usec);
 294
 295                igc_lower_eec_clk(hw, &eecd);
 296        } else if (nvm->type == igc_nvm_eeprom_spi) {
 297                /* Toggle CS to flush commands */
 298                eecd |= IGC_EECD_CS;
 299                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 300                IGC_WRITE_FLUSH(hw);
 301                usec_delay(nvm->delay_usec);
 302                eecd &= ~IGC_EECD_CS;
 303                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 304                IGC_WRITE_FLUSH(hw);
 305                usec_delay(nvm->delay_usec);
 306        }
 307}
 308
 309/**
 310 *  igc_stop_nvm - Terminate EEPROM command
 311 *  @hw: pointer to the HW structure
 312 *
 313 *  Terminates the current command by inverting the EEPROM's chip select pin.
 314 **/
 315void igc_stop_nvm(struct igc_hw *hw)
 316{
 317        u32 eecd;
 318
 319        DEBUGFUNC("igc_stop_nvm");
 320
 321        eecd = IGC_READ_REG(hw, IGC_EECD);
 322        if (hw->nvm.type == igc_nvm_eeprom_spi) {
 323                /* Pull CS high */
 324                eecd |= IGC_EECD_CS;
 325                igc_lower_eec_clk(hw, &eecd);
 326        } else if (hw->nvm.type == igc_nvm_eeprom_microwire) {
 327                /* CS on Microwire is active-high */
 328                eecd &= ~(IGC_EECD_CS | IGC_EECD_DI);
 329                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 330                igc_raise_eec_clk(hw, &eecd);
 331                igc_lower_eec_clk(hw, &eecd);
 332        }
 333}
 334
 335/**
 336 *  igc_release_nvm_generic - Release exclusive access to EEPROM
 337 *  @hw: pointer to the HW structure
 338 *
 339 *  Stop any current commands to the EEPROM and clear the EEPROM request bit.
 340 **/
 341void igc_release_nvm_generic(struct igc_hw *hw)
 342{
 343        u32 eecd;
 344
 345        DEBUGFUNC("igc_release_nvm_generic");
 346
 347        igc_stop_nvm(hw);
 348
 349        eecd = IGC_READ_REG(hw, IGC_EECD);
 350        eecd &= ~IGC_EECD_REQ;
 351        IGC_WRITE_REG(hw, IGC_EECD, eecd);
 352}
 353
 354/**
 355 *  igc_ready_nvm_eeprom - Prepares EEPROM for read/write
 356 *  @hw: pointer to the HW structure
 357 *
 358 *  Setups the EEPROM for reading and writing.
 359 **/
 360static s32 igc_ready_nvm_eeprom(struct igc_hw *hw)
 361{
 362        struct igc_nvm_info *nvm = &hw->nvm;
 363        u32 eecd = IGC_READ_REG(hw, IGC_EECD);
 364        u8 spi_stat_reg;
 365
 366        DEBUGFUNC("igc_ready_nvm_eeprom");
 367
 368        if (nvm->type == igc_nvm_eeprom_microwire) {
 369                /* Clear SK and DI */
 370                eecd &= ~(IGC_EECD_DI | IGC_EECD_SK);
 371                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 372                /* Set CS */
 373                eecd |= IGC_EECD_CS;
 374                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 375        } else if (nvm->type == igc_nvm_eeprom_spi) {
 376                u16 timeout = NVM_MAX_RETRY_SPI;
 377
 378                /* Clear SK and CS */
 379                eecd &= ~(IGC_EECD_CS | IGC_EECD_SK);
 380                IGC_WRITE_REG(hw, IGC_EECD, eecd);
 381                IGC_WRITE_FLUSH(hw);
 382                usec_delay(1);
 383
 384                /* Read "Status Register" repeatedly until the LSB is cleared.
 385                 * The EEPROM will signal that the command has been completed
 386                 * by clearing bit 0 of the internal status register.  If it's
 387                 * not cleared within 'timeout', then error out.
 388                 */
 389                while (timeout) {
 390                        igc_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI,
 391                                                 hw->nvm.opcode_bits);
 392                        spi_stat_reg = (u8)igc_shift_in_eec_bits(hw, 8);
 393                        if (!(spi_stat_reg & NVM_STATUS_RDY_SPI))
 394                                break;
 395
 396                        usec_delay(5);
 397                        igc_standby_nvm(hw);
 398                        timeout--;
 399                }
 400
 401                if (!timeout) {
 402                        DEBUGOUT("SPI NVM Status error\n");
 403                        return -IGC_ERR_NVM;
 404                }
 405        }
 406
 407        return IGC_SUCCESS;
 408}
 409
 410/**
 411 *  igc_read_nvm_spi - Read EEPROM's using SPI
 412 *  @hw: pointer to the HW structure
 413 *  @offset: offset of word in the EEPROM to read
 414 *  @words: number of words to read
 415 *  @data: word read from the EEPROM
 416 *
 417 *  Reads a 16 bit word from the EEPROM.
 418 **/
 419s32 igc_read_nvm_spi(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
 420{
 421        struct igc_nvm_info *nvm = &hw->nvm;
 422        u32 i = 0;
 423        s32 ret_val;
 424        u16 word_in;
 425        u8 read_opcode = NVM_READ_OPCODE_SPI;
 426
 427        DEBUGFUNC("igc_read_nvm_spi");
 428
 429        /* A check for invalid values:  offset too large, too many words,
 430         * and not enough words.
 431         */
 432        if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
 433                        words == 0) {
 434                DEBUGOUT("nvm parameter(s) out of bounds\n");
 435                return -IGC_ERR_NVM;
 436        }
 437
 438        ret_val = nvm->ops.acquire(hw);
 439        if (ret_val)
 440                return ret_val;
 441
 442        ret_val = igc_ready_nvm_eeprom(hw);
 443        if (ret_val)
 444                goto release;
 445
 446        igc_standby_nvm(hw);
 447
 448        if (nvm->address_bits == 8 && offset >= 128)
 449                read_opcode |= NVM_A8_OPCODE_SPI;
 450
 451        /* Send the READ command (opcode + addr) */
 452        igc_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
 453        igc_shift_out_eec_bits(hw, (u16)(offset * 2), nvm->address_bits);
 454
 455        /* Read the data.  SPI NVMs increment the address with each byte
 456         * read and will roll over if reading beyond the end.  This allows
 457         * us to read the whole NVM from any offset
 458         */
 459        for (i = 0; i < words; i++) {
 460                word_in = igc_shift_in_eec_bits(hw, 16);
 461                data[i] = (word_in >> 8) | (word_in << 8);
 462        }
 463
 464release:
 465        nvm->ops.release(hw);
 466
 467        return ret_val;
 468}
 469
 470/**
 471 *  igc_read_nvm_microwire - Reads EEPROM's using microwire
 472 *  @hw: pointer to the HW structure
 473 *  @offset: offset of word in the EEPROM to read
 474 *  @words: number of words to read
 475 *  @data: word read from the EEPROM
 476 *
 477 *  Reads a 16 bit word from the EEPROM.
 478 **/
 479s32 igc_read_nvm_microwire(struct igc_hw *hw, u16 offset, u16 words,
 480                             u16 *data)
 481{
 482        struct igc_nvm_info *nvm = &hw->nvm;
 483        u32 i = 0;
 484        s32 ret_val;
 485        u8 read_opcode = NVM_READ_OPCODE_MICROWIRE;
 486
 487        DEBUGFUNC("igc_read_nvm_microwire");
 488
 489        /* A check for invalid values:  offset too large, too many words,
 490         * and not enough words.
 491         */
 492        if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
 493                        words == 0) {
 494                DEBUGOUT("nvm parameter(s) out of bounds\n");
 495                return -IGC_ERR_NVM;
 496        }
 497
 498        ret_val = nvm->ops.acquire(hw);
 499        if (ret_val)
 500                return ret_val;
 501
 502        ret_val = igc_ready_nvm_eeprom(hw);
 503        if (ret_val)
 504                goto release;
 505
 506        for (i = 0; i < words; i++) {
 507                /* Send the READ command (opcode + addr) */
 508                igc_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
 509                igc_shift_out_eec_bits(hw, (u16)(offset + i),
 510                                        nvm->address_bits);
 511
 512                /* Read the data.  For microwire, each word requires the
 513                 * overhead of setup and tear-down.
 514                 */
 515                data[i] = igc_shift_in_eec_bits(hw, 16);
 516                igc_standby_nvm(hw);
 517        }
 518
 519release:
 520        nvm->ops.release(hw);
 521
 522        return ret_val;
 523}
 524
 525/**
 526 *  igc_read_nvm_eerd - Reads EEPROM using EERD register
 527 *  @hw: pointer to the HW structure
 528 *  @offset: offset of word in the EEPROM to read
 529 *  @words: number of words to read
 530 *  @data: word read from the EEPROM
 531 *
 532 *  Reads a 16 bit word from the EEPROM using the EERD register.
 533 **/
 534s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
 535{
 536        struct igc_nvm_info *nvm = &hw->nvm;
 537        u32 i, eerd = 0;
 538        s32 ret_val = IGC_SUCCESS;
 539
 540        DEBUGFUNC("igc_read_nvm_eerd");
 541
 542        /* A check for invalid values:  offset too large, too many words,
 543         * too many words for the offset, and not enough words.
 544         */
 545        if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
 546                        words == 0) {
 547                DEBUGOUT("nvm parameter(s) out of bounds\n");
 548                return -IGC_ERR_NVM;
 549        }
 550
 551        for (i = 0; i < words; i++) {
 552                eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
 553                       IGC_NVM_RW_REG_START;
 554
 555                IGC_WRITE_REG(hw, IGC_EERD, eerd);
 556                ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
 557                if (ret_val)
 558                        break;
 559
 560                data[i] = (IGC_READ_REG(hw, IGC_EERD) >>
 561                           IGC_NVM_RW_REG_DATA);
 562        }
 563
 564        if (ret_val)
 565                DEBUGOUT1("NVM read error: %d\n", ret_val);
 566
 567        return ret_val;
 568}
 569
 570/**
 571 *  igc_write_nvm_spi - Write to EEPROM using SPI
 572 *  @hw: pointer to the HW structure
 573 *  @offset: offset within the EEPROM to be written to
 574 *  @words: number of words to write
 575 *  @data: 16 bit word(s) to be written to the EEPROM
 576 *
 577 *  Writes data to EEPROM at offset using SPI interface.
 578 *
 579 *  If igc_update_nvm_checksum is not called after this function , the
 580 *  EEPROM will most likely contain an invalid checksum.
 581 **/
 582s32 igc_write_nvm_spi(struct igc_hw *hw, u16 offset, u16 words, u16 *data)
 583{
 584        struct igc_nvm_info *nvm = &hw->nvm;
 585        s32 ret_val = -IGC_ERR_NVM;
 586        u16 widx = 0;
 587
 588        DEBUGFUNC("igc_write_nvm_spi");
 589
 590        /* A check for invalid values:  offset too large, too many words,
 591         * and not enough words.
 592         */
 593        if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
 594                        words == 0) {
 595                DEBUGOUT("nvm parameter(s) out of bounds\n");
 596                return -IGC_ERR_NVM;
 597        }
 598
 599        while (widx < words) {
 600                u8 write_opcode = NVM_WRITE_OPCODE_SPI;
 601
 602                ret_val = nvm->ops.acquire(hw);
 603                if (ret_val)
 604                        return ret_val;
 605
 606                ret_val = igc_ready_nvm_eeprom(hw);
 607                if (ret_val) {
 608                        nvm->ops.release(hw);
 609                        return ret_val;
 610                }
 611
 612                igc_standby_nvm(hw);
 613
 614                /* Send the WRITE ENABLE command (8 bit opcode) */
 615                igc_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI,
 616                                         nvm->opcode_bits);
 617
 618                igc_standby_nvm(hw);
 619
 620                /* Some SPI eeproms use the 8th address bit embedded in the
 621                 * opcode
 622                 */
 623                if (nvm->address_bits == 8 && offset >= 128)
 624                        write_opcode |= NVM_A8_OPCODE_SPI;
 625
 626                /* Send the Write command (8-bit opcode + addr) */
 627                igc_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits);
 628                igc_shift_out_eec_bits(hw, (u16)((offset + widx) * 2),
 629                                         nvm->address_bits);
 630
 631                /* Loop to allow for up to whole page write of eeprom */
 632                while (widx < words) {
 633                        u16 word_out = data[widx];
 634                        word_out = (word_out >> 8) | (word_out << 8);
 635                        igc_shift_out_eec_bits(hw, word_out, 16);
 636                        widx++;
 637
 638                        if ((((offset + widx) * 2) % nvm->page_size) == 0) {
 639                                igc_standby_nvm(hw);
 640                                break;
 641                        }
 642                }
 643                msec_delay(10);
 644                nvm->ops.release(hw);
 645        }
 646
 647        return ret_val;
 648}
 649
 650/**
 651 *  igc_write_nvm_microwire - Writes EEPROM using microwire
 652 *  @hw: pointer to the HW structure
 653 *  @offset: offset within the EEPROM to be written to
 654 *  @words: number of words to write
 655 *  @data: 16 bit word(s) to be written to the EEPROM
 656 *
 657 *  Writes data to EEPROM at offset using microwire interface.
 658 *
 659 *  If igc_update_nvm_checksum is not called after this function , the
 660 *  EEPROM will most likely contain an invalid checksum.
 661 **/
 662s32 igc_write_nvm_microwire(struct igc_hw *hw, u16 offset, u16 words,
 663                              u16 *data)
 664{
 665        struct igc_nvm_info *nvm = &hw->nvm;
 666        s32  ret_val;
 667        u32 eecd;
 668        u16 words_written = 0;
 669        u16 widx = 0;
 670
 671        DEBUGFUNC("igc_write_nvm_microwire");
 672
 673        /* A check for invalid values:  offset too large, too many words,
 674         * and not enough words.
 675         */
 676        if (offset >= nvm->word_size || words > (nvm->word_size - offset) ||
 677                        words == 0) {
 678                DEBUGOUT("nvm parameter(s) out of bounds\n");
 679                return -IGC_ERR_NVM;
 680        }
 681
 682        ret_val = nvm->ops.acquire(hw);
 683        if (ret_val)
 684                return ret_val;
 685
 686        ret_val = igc_ready_nvm_eeprom(hw);
 687        if (ret_val)
 688                goto release;
 689
 690        igc_shift_out_eec_bits(hw, NVM_EWEN_OPCODE_MICROWIRE,
 691                                 (u16)(nvm->opcode_bits + 2));
 692
 693        igc_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
 694
 695        igc_standby_nvm(hw);
 696
 697        while (words_written < words) {
 698                igc_shift_out_eec_bits(hw, NVM_WRITE_OPCODE_MICROWIRE,
 699                                         nvm->opcode_bits);
 700
 701                igc_shift_out_eec_bits(hw, (u16)(offset + words_written),
 702                                         nvm->address_bits);
 703
 704                igc_shift_out_eec_bits(hw, data[words_written], 16);
 705
 706                igc_standby_nvm(hw);
 707
 708                for (widx = 0; widx < 200; widx++) {
 709                        eecd = IGC_READ_REG(hw, IGC_EECD);
 710                        if (eecd & IGC_EECD_DO)
 711                                break;
 712                        usec_delay(50);
 713                }
 714
 715                if (widx == 200) {
 716                        DEBUGOUT("NVM Write did not complete\n");
 717                        ret_val = -IGC_ERR_NVM;
 718                        goto release;
 719                }
 720
 721                igc_standby_nvm(hw);
 722
 723                words_written++;
 724        }
 725
 726        igc_shift_out_eec_bits(hw, NVM_EWDS_OPCODE_MICROWIRE,
 727                                 (u16)(nvm->opcode_bits + 2));
 728
 729        igc_shift_out_eec_bits(hw, 0, (u16)(nvm->address_bits - 2));
 730
 731release:
 732        nvm->ops.release(hw);
 733
 734        return ret_val;
 735}
 736
 737/**
 738 *  igc_read_pba_string_generic - Read device part number
 739 *  @hw: pointer to the HW structure
 740 *  @pba_num: pointer to device part number
 741 *  @pba_num_size: size of part number buffer
 742 *
 743 *  Reads the product board assembly (PBA) number from the EEPROM and stores
 744 *  the value in pba_num.
 745 **/
 746s32 igc_read_pba_string_generic(struct igc_hw *hw, u8 *pba_num,
 747                                  u32 pba_num_size)
 748{
 749        s32 ret_val;
 750        u16 nvm_data;
 751        u16 pba_ptr;
 752        u16 offset;
 753        u16 length;
 754
 755        DEBUGFUNC("igc_read_pba_string_generic");
 756
 757        if (pba_num == NULL) {
 758                DEBUGOUT("PBA string buffer was null\n");
 759                return -IGC_ERR_INVALID_ARGUMENT;
 760        }
 761
 762        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
 763        if (ret_val) {
 764                DEBUGOUT("NVM Read Error\n");
 765                return ret_val;
 766        }
 767
 768        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
 769        if (ret_val) {
 770                DEBUGOUT("NVM Read Error\n");
 771                return ret_val;
 772        }
 773
 774        /* if nvm_data is not ptr guard the PBA must be in legacy format which
 775         * means pba_ptr is actually our second data word for the PBA number
 776         * and we can decode it into an ascii string
 777         */
 778        if (nvm_data != NVM_PBA_PTR_GUARD) {
 779                DEBUGOUT("NVM PBA number is not stored as string\n");
 780
 781                /* make sure callers buffer is big enough to store the PBA */
 782                if (pba_num_size < IGC_PBANUM_LENGTH) {
 783                        DEBUGOUT("PBA string buffer too small\n");
 784                        return IGC_ERR_NO_SPACE;
 785                }
 786
 787                /* extract hex string from data and pba_ptr */
 788                pba_num[0] = (nvm_data >> 12) & 0xF;
 789                pba_num[1] = (nvm_data >> 8) & 0xF;
 790                pba_num[2] = (nvm_data >> 4) & 0xF;
 791                pba_num[3] = nvm_data & 0xF;
 792                pba_num[4] = (pba_ptr >> 12) & 0xF;
 793                pba_num[5] = (pba_ptr >> 8) & 0xF;
 794                pba_num[6] = '-';
 795                pba_num[7] = 0;
 796                pba_num[8] = (pba_ptr >> 4) & 0xF;
 797                pba_num[9] = pba_ptr & 0xF;
 798
 799                /* put a null character on the end of our string */
 800                pba_num[10] = '\0';
 801
 802                /* switch all the data but the '-' to hex char */
 803                for (offset = 0; offset < 10; offset++) {
 804                        if (pba_num[offset] < 0xA)
 805                                pba_num[offset] += '0';
 806                        else if (pba_num[offset] < 0x10)
 807                                pba_num[offset] += 'A' - 0xA;
 808                }
 809
 810                return IGC_SUCCESS;
 811        }
 812
 813        ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
 814        if (ret_val) {
 815                DEBUGOUT("NVM Read Error\n");
 816                return ret_val;
 817        }
 818
 819        if (length == 0xFFFF || length == 0) {
 820                DEBUGOUT("NVM PBA number section invalid length\n");
 821                return -IGC_ERR_NVM_PBA_SECTION;
 822        }
 823        /* check if pba_num buffer is big enough */
 824        if (pba_num_size < (((u32)length * 2) - 1)) {
 825                DEBUGOUT("PBA string buffer too small\n");
 826                return -IGC_ERR_NO_SPACE;
 827        }
 828
 829        /* trim pba length from start of string */
 830        pba_ptr++;
 831        length--;
 832
 833        for (offset = 0; offset < length; offset++) {
 834                ret_val = hw->nvm.ops.read(hw, pba_ptr + offset, 1, &nvm_data);
 835                if (ret_val) {
 836                        DEBUGOUT("NVM Read Error\n");
 837                        return ret_val;
 838                }
 839                pba_num[offset * 2] = (u8)(nvm_data >> 8);
 840                pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF);
 841        }
 842        pba_num[offset * 2] = '\0';
 843
 844        return IGC_SUCCESS;
 845}
 846
 847/**
 848 *  igc_read_pba_length_generic - Read device part number length
 849 *  @hw: pointer to the HW structure
 850 *  @pba_num_size: size of part number buffer
 851 *
 852 *  Reads the product board assembly (PBA) number length from the EEPROM and
 853 *  stores the value in pba_num_size.
 854 **/
 855s32 igc_read_pba_length_generic(struct igc_hw *hw, u32 *pba_num_size)
 856{
 857        s32 ret_val;
 858        u16 nvm_data;
 859        u16 pba_ptr;
 860        u16 length;
 861
 862        DEBUGFUNC("igc_read_pba_length_generic");
 863
 864        if (pba_num_size == NULL) {
 865                DEBUGOUT("PBA buffer size was null\n");
 866                return -IGC_ERR_INVALID_ARGUMENT;
 867        }
 868
 869        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
 870        if (ret_val) {
 871                DEBUGOUT("NVM Read Error\n");
 872                return ret_val;
 873        }
 874
 875        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr);
 876        if (ret_val) {
 877                DEBUGOUT("NVM Read Error\n");
 878                return ret_val;
 879        }
 880
 881         /* if data is not ptr guard the PBA must be in legacy format */
 882        if (nvm_data != NVM_PBA_PTR_GUARD) {
 883                *pba_num_size = IGC_PBANUM_LENGTH;
 884                return IGC_SUCCESS;
 885        }
 886
 887        ret_val = hw->nvm.ops.read(hw, pba_ptr, 1, &length);
 888        if (ret_val) {
 889                DEBUGOUT("NVM Read Error\n");
 890                return ret_val;
 891        }
 892
 893        if (length == 0xFFFF || length == 0) {
 894                DEBUGOUT("NVM PBA number section invalid length\n");
 895                return -IGC_ERR_NVM_PBA_SECTION;
 896        }
 897
 898        /* Convert from length in u16 values to u8 chars, add 1 for NULL,
 899         * and subtract 2 because length field is included in length.
 900         */
 901        *pba_num_size = ((u32)length * 2) - 1;
 902
 903        return IGC_SUCCESS;
 904}
 905
 906/**
 907 *  igc_read_pba_num_generic - Read device part number
 908 *  @hw: pointer to the HW structure
 909 *  @pba_num: pointer to device part number
 910 *
 911 *  Reads the product board assembly (PBA) number from the EEPROM and stores
 912 *  the value in pba_num.
 913 **/
 914s32 igc_read_pba_num_generic(struct igc_hw *hw, u32 *pba_num)
 915{
 916        s32 ret_val;
 917        u16 nvm_data;
 918
 919        DEBUGFUNC("igc_read_pba_num_generic");
 920
 921        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_0, 1, &nvm_data);
 922        if (ret_val) {
 923                DEBUGOUT("NVM Read Error\n");
 924                return ret_val;
 925        } else if (nvm_data == NVM_PBA_PTR_GUARD) {
 926                DEBUGOUT("NVM Not Supported\n");
 927                return -IGC_NOT_IMPLEMENTED;
 928        }
 929        *pba_num = (u32)(nvm_data << 16);
 930
 931        ret_val = hw->nvm.ops.read(hw, NVM_PBA_OFFSET_1, 1, &nvm_data);
 932        if (ret_val) {
 933                DEBUGOUT("NVM Read Error\n");
 934                return ret_val;
 935        }
 936        *pba_num |= nvm_data;
 937
 938        return IGC_SUCCESS;
 939}
 940
 941
 942/**
 943 *  igc_read_pba_raw
 944 *  @hw: pointer to the HW structure
 945 *  @eeprom_buf: optional pointer to EEPROM image
 946 *  @eeprom_buf_size: size of EEPROM image in words
 947 *  @max_pba_block_size: PBA block size limit
 948 *  @pba: pointer to output PBA structure
 949 *
 950 *  Reads PBA from EEPROM image when eeprom_buf is not NULL.
 951 *  Reads PBA from physical EEPROM device when eeprom_buf is NULL.
 952 *
 953 **/
 954s32 igc_read_pba_raw(struct igc_hw *hw, u16 *eeprom_buf,
 955                       u32 eeprom_buf_size, u16 max_pba_block_size,
 956                       struct igc_pba *pba)
 957{
 958        s32 ret_val;
 959        u16 pba_block_size;
 960
 961        if (pba == NULL)
 962                return -IGC_ERR_PARAM;
 963
 964        if (eeprom_buf == NULL) {
 965                ret_val = igc_read_nvm(hw, NVM_PBA_OFFSET_0, 2,
 966                                         &pba->word[0]);
 967                if (ret_val)
 968                        return ret_val;
 969        } else {
 970                if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
 971                        pba->word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
 972                        pba->word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
 973                } else {
 974                        return -IGC_ERR_PARAM;
 975                }
 976        }
 977
 978        if (pba->word[0] == NVM_PBA_PTR_GUARD) {
 979                if (pba->pba_block == NULL)
 980                        return -IGC_ERR_PARAM;
 981
 982                ret_val = igc_get_pba_block_size(hw, eeprom_buf,
 983                                                   eeprom_buf_size,
 984                                                   &pba_block_size);
 985                if (ret_val)
 986                        return ret_val;
 987
 988                if (pba_block_size > max_pba_block_size)
 989                        return -IGC_ERR_PARAM;
 990
 991                if (eeprom_buf == NULL) {
 992                        ret_val = igc_read_nvm(hw, pba->word[1],
 993                                                 pba_block_size,
 994                                                 pba->pba_block);
 995                        if (ret_val)
 996                                return ret_val;
 997                } else {
 998                        if (eeprom_buf_size > (u32)(pba->word[1] +
 999                                              pba_block_size)) {
1000                                memcpy(pba->pba_block,
1001                                       &eeprom_buf[pba->word[1]],
1002                                       pba_block_size * sizeof(u16));
1003                        } else {
1004                                return -IGC_ERR_PARAM;
1005                        }
1006                }
1007        }
1008
1009        return IGC_SUCCESS;
1010}
1011
1012/**
1013 *  igc_write_pba_raw
1014 *  @hw: pointer to the HW structure
1015 *  @eeprom_buf: optional pointer to EEPROM image
1016 *  @eeprom_buf_size: size of EEPROM image in words
1017 *  @pba: pointer to PBA structure
1018 *
1019 *  Writes PBA to EEPROM image when eeprom_buf is not NULL.
1020 *  Writes PBA to physical EEPROM device when eeprom_buf is NULL.
1021 *
1022 **/
1023s32 igc_write_pba_raw(struct igc_hw *hw, u16 *eeprom_buf,
1024                        u32 eeprom_buf_size, struct igc_pba *pba)
1025{
1026        s32 ret_val;
1027
1028        if (pba == NULL)
1029                return -IGC_ERR_PARAM;
1030
1031        if (eeprom_buf == NULL) {
1032                ret_val = igc_write_nvm(hw, NVM_PBA_OFFSET_0, 2,
1033                                          &pba->word[0]);
1034                if (ret_val)
1035                        return ret_val;
1036        } else {
1037                if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
1038                        eeprom_buf[NVM_PBA_OFFSET_0] = pba->word[0];
1039                        eeprom_buf[NVM_PBA_OFFSET_1] = pba->word[1];
1040                } else {
1041                        return -IGC_ERR_PARAM;
1042                }
1043        }
1044
1045        if (pba->word[0] == NVM_PBA_PTR_GUARD) {
1046                if (pba->pba_block == NULL)
1047                        return -IGC_ERR_PARAM;
1048
1049                if (eeprom_buf == NULL) {
1050                        ret_val = igc_write_nvm(hw, pba->word[1],
1051                                                  pba->pba_block[0],
1052                                                  pba->pba_block);
1053                        if (ret_val)
1054                                return ret_val;
1055                } else {
1056                        if (eeprom_buf_size > (u32)(pba->word[1] +
1057                                              pba->pba_block[0])) {
1058                                memcpy(&eeprom_buf[pba->word[1]],
1059                                       pba->pba_block,
1060                                       pba->pba_block[0] * sizeof(u16));
1061                        } else {
1062                                return -IGC_ERR_PARAM;
1063                        }
1064                }
1065        }
1066
1067        return IGC_SUCCESS;
1068}
1069
1070/**
1071 *  igc_get_pba_block_size
1072 *  @hw: pointer to the HW structure
1073 *  @eeprom_buf: optional pointer to EEPROM image
1074 *  @eeprom_buf_size: size of EEPROM image in words
1075 *  @pba_data_size: pointer to output variable
1076 *
1077 *  Returns the size of the PBA block in words. Function operates on EEPROM
1078 *  image if the eeprom_buf pointer is not NULL otherwise it accesses physical
1079 *  EEPROM device.
1080 *
1081 **/
1082s32 igc_get_pba_block_size(struct igc_hw *hw, u16 *eeprom_buf,
1083                             u32 eeprom_buf_size, u16 *pba_block_size)
1084{
1085        s32 ret_val;
1086        u16 pba_word[2];
1087        u16 length;
1088
1089        DEBUGFUNC("igc_get_pba_block_size");
1090
1091        if (eeprom_buf == NULL) {
1092                ret_val = igc_read_nvm(hw, NVM_PBA_OFFSET_0, 2, &pba_word[0]);
1093                if (ret_val)
1094                        return ret_val;
1095        } else {
1096                if (eeprom_buf_size > NVM_PBA_OFFSET_1) {
1097                        pba_word[0] = eeprom_buf[NVM_PBA_OFFSET_0];
1098                        pba_word[1] = eeprom_buf[NVM_PBA_OFFSET_1];
1099                } else {
1100                        return -IGC_ERR_PARAM;
1101                }
1102        }
1103
1104        if (pba_word[0] == NVM_PBA_PTR_GUARD) {
1105                if (eeprom_buf == NULL) {
1106                        ret_val = igc_read_nvm(hw, pba_word[1] + 0, 1,
1107                                                 &length);
1108                        if (ret_val)
1109                                return ret_val;
1110                } else {
1111                        if (eeprom_buf_size > pba_word[1])
1112                                length = eeprom_buf[pba_word[1] + 0];
1113                        else
1114                                return -IGC_ERR_PARAM;
1115                }
1116
1117                if (length == 0xFFFF || length == 0)
1118                        return -IGC_ERR_NVM_PBA_SECTION;
1119        } else {
1120                /* PBA number in legacy format, there is no PBA Block. */
1121                length = 0;
1122        }
1123
1124        if (pba_block_size != NULL)
1125                *pba_block_size = length;
1126
1127        return IGC_SUCCESS;
1128}
1129
1130/**
1131 *  igc_read_mac_addr_generic - Read device MAC address
1132 *  @hw: pointer to the HW structure
1133 *
1134 *  Reads the device MAC address from the EEPROM and stores the value.
1135 *  Since devices with two ports use the same EEPROM, we increment the
1136 *  last bit in the MAC address for the second port.
1137 **/
1138s32 igc_read_mac_addr_generic(struct igc_hw *hw)
1139{
1140        u32 rar_high;
1141        u32 rar_low;
1142        u16 i;
1143
1144        rar_high = IGC_READ_REG(hw, IGC_RAH(0));
1145        rar_low = IGC_READ_REG(hw, IGC_RAL(0));
1146
1147        for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
1148                hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8));
1149
1150        for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
1151                hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8));
1152
1153        for (i = 0; i < ETH_ADDR_LEN; i++)
1154                hw->mac.addr[i] = hw->mac.perm_addr[i];
1155
1156        return IGC_SUCCESS;
1157}
1158
1159/**
1160 *  igc_validate_nvm_checksum_generic - Validate EEPROM checksum
1161 *  @hw: pointer to the HW structure
1162 *
1163 *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
1164 *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
1165 **/
1166s32 igc_validate_nvm_checksum_generic(struct igc_hw *hw)
1167{
1168        s32 ret_val;
1169        u16 checksum = 0;
1170        u16 i, nvm_data;
1171
1172        DEBUGFUNC("igc_validate_nvm_checksum_generic");
1173
1174        for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
1175                ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
1176                if (ret_val) {
1177                        DEBUGOUT("NVM Read Error\n");
1178                        return ret_val;
1179                }
1180                checksum += nvm_data;
1181        }
1182
1183        if (checksum != (u16)NVM_SUM) {
1184                DEBUGOUT("NVM Checksum Invalid\n");
1185                return -IGC_ERR_NVM;
1186        }
1187
1188        return IGC_SUCCESS;
1189}
1190
1191/**
1192 *  igc_update_nvm_checksum_generic - Update EEPROM checksum
1193 *  @hw: pointer to the HW structure
1194 *
1195 *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
1196 *  up to the checksum.  Then calculates the EEPROM checksum and writes the
1197 *  value to the EEPROM.
1198 **/
1199s32 igc_update_nvm_checksum_generic(struct igc_hw *hw)
1200{
1201        s32 ret_val;
1202        u16 checksum = 0;
1203        u16 i, nvm_data;
1204
1205        DEBUGFUNC("igc_update_nvm_checksum");
1206
1207        for (i = 0; i < NVM_CHECKSUM_REG; i++) {
1208                ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
1209                if (ret_val) {
1210                        DEBUGOUT("NVM Read Error while updating checksum.\n");
1211                        return ret_val;
1212                }
1213                checksum += nvm_data;
1214        }
1215        checksum = (u16)NVM_SUM - checksum;
1216        ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum);
1217        if (ret_val)
1218                DEBUGOUT("NVM Write Error while updating checksum.\n");
1219
1220        return ret_val;
1221}
1222
1223/**
1224 *  igc_reload_nvm_generic - Reloads EEPROM
1225 *  @hw: pointer to the HW structure
1226 *
1227 *  Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
1228 *  extended control register.
1229 **/
1230static void igc_reload_nvm_generic(struct igc_hw *hw)
1231{
1232        u32 ctrl_ext;
1233
1234        DEBUGFUNC("igc_reload_nvm_generic");
1235
1236        usec_delay(10);
1237        ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
1238        ctrl_ext |= IGC_CTRL_EXT_EE_RST;
1239        IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
1240        IGC_WRITE_FLUSH(hw);
1241}
1242
1243/**
1244 *  igc_get_fw_version - Get firmware version information
1245 *  @hw: pointer to the HW structure
1246 *  @fw_vers: pointer to output version structure
1247 *
1248 *  unsupported/not present features return 0 in version structure
1249 **/
1250void igc_get_fw_version(struct igc_hw *hw, struct igc_fw_version *fw_vers)
1251{
1252        u16 eeprom_verh, eeprom_verl, etrack_test, fw_version;
1253        u8 q, hval, rem, result;
1254        u16 comb_verh, comb_verl, comb_offset;
1255
1256        memset(fw_vers, 0, sizeof(struct igc_fw_version));
1257
1258        /*
1259         * basic eeprom version numbers, bits used vary by part and by tool
1260         * used to create the nvm images. Check which data format we have.
1261         */
1262        switch (hw->mac.type) {
1263        case igc_i225:
1264                hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
1265                /* find combo image version */
1266                hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
1267                if (comb_offset && comb_offset != NVM_VER_INVALID) {
1268                        hw->nvm.ops.read(hw, NVM_COMB_VER_OFF + comb_offset + 1,
1269                                        1, &comb_verh);
1270                        hw->nvm.ops.read(hw, NVM_COMB_VER_OFF + comb_offset,
1271                                        1, &comb_verl);
1272
1273                        /* get Option Rom version if it exists and is valid */
1274                        if (comb_verh && comb_verl &&
1275                                        comb_verh != NVM_VER_INVALID &&
1276                                        comb_verl != NVM_VER_INVALID) {
1277                                fw_vers->or_valid = true;
1278                                fw_vers->or_major = comb_verl >>
1279                                                NVM_COMB_VER_SHFT;
1280                                fw_vers->or_build = (comb_verl <<
1281                                                NVM_COMB_VER_SHFT) |
1282                                                (comb_verh >>
1283                                                NVM_COMB_VER_SHFT);
1284                                fw_vers->or_patch = comb_verh &
1285                                                NVM_COMB_VER_MASK;
1286                        }
1287                }
1288                break;
1289        default:
1290                hw->nvm.ops.read(hw, NVM_ETRACK_HIWORD, 1, &etrack_test);
1291                return;
1292        }
1293        hw->nvm.ops.read(hw, NVM_VERSION, 1, &fw_version);
1294        fw_vers->eep_major = (fw_version & NVM_MAJOR_MASK)
1295                              >> NVM_MAJOR_SHIFT;
1296
1297        /* check for old style version format in newer images*/
1298        if ((fw_version & NVM_NEW_DEC_MASK) == 0x0) {
1299                eeprom_verl = (fw_version & NVM_COMB_VER_MASK);
1300        } else {
1301                eeprom_verl = (fw_version & NVM_MINOR_MASK)
1302                                >> NVM_MINOR_SHIFT;
1303        }
1304        /* Convert minor value to hex before assigning to output struct
1305         * Val to be converted will not be higher than 99, per tool output
1306         */
1307        q = eeprom_verl / NVM_HEX_CONV;
1308        hval = q * NVM_HEX_TENS;
1309        rem = eeprom_verl % NVM_HEX_CONV;
1310        result = hval + rem;
1311        fw_vers->eep_minor = result;
1312
1313        if ((etrack_test &  NVM_MAJOR_MASK) == NVM_ETRACK_VALID) {
1314                hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verl);
1315                hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verh);
1316                fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT)
1317                        | eeprom_verl;
1318        } else if ((etrack_test & NVM_ETRACK_VALID) == 0) {
1319                hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
1320                hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
1321                fw_vers->etrack_id = (eeprom_verh << NVM_ETRACK_SHIFT) |
1322                                     eeprom_verl;
1323        }
1324}
1325