Re: support em(4) i210/i211 OTP chips

2015-03-18 Thread Patrick Wildt
Any updates on this?

 Am 09.03.2015 um 07:32 schrieb Patrick Wildt m...@patrick-wildt.de:
 
 Hi,
 
 this diff adds support for a special configuration of i210/i211 chips.
 
 Those can have a OTP chip instead of the usual EEPROM, so this diff
 adds the infrastructure to read needed data from OTP and have it not
 bail out when there's no EEPROM.
 
 \Patrick
 
 diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
 index 8717fa4..10cdc52 100644
 --- sys/dev/pci/if_em.c
 +++ sys/dev/pci/if_em.c
 @@ -1775,7 +1775,8 @@ em_hardware_init(struct em_softc *sc)
   sc-tx_fifo_head = 0;
 
   /* Make sure we have a good EEPROM before we read from it */
 - if (em_validate_eeprom_checksum(sc-hw)  0) {
 + if (em_get_flash_presence_i210(sc-hw) 
 + em_validate_eeprom_checksum(sc-hw)  0) {
   /*
* Some PCIe parts fail the first check due to
* the link being in sleep state, call it again,
 @@ -1788,7 +1789,8 @@ em_hardware_init(struct em_softc *sc)
   }
   }
 
 - if (em_read_part_num(sc-hw, (sc-part_num))  0) {
 + if (em_get_flash_presence_i210(sc-hw) 
 + em_read_part_num(sc-hw, (sc-part_num))  0) {
   printf(%s: EEPROM read error while reading part number\n,
  sc-sc_dv.dv_xname);
   return (EIO);
 diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
 index 16cd3ee..4994c4d 100644
 --- sys/dev/pci/if_em_hw.c
 +++ sys/dev/pci/if_em_hw.c
 @@ -113,6 +113,9 @@ static int32_tem_read_eeprom_ich8(struct em_hw *, 
 uint16_t, uint16_t,
   uint16_t *);
 static int32_tem_write_eeprom_ich8(struct em_hw *, uint16_t, uint16_t,
   uint16_t *);
 +static int32_t   em_read_invm_i210(struct em_hw *, uint16_t, uint16_t,
 + uint16_t *);
 +static int32_t   em_read_invm_word_i210(struct em_hw *, uint16_t, 
 uint16_t *);
 static void   em_release_software_flag(struct em_hw *);
 static int32_tem_set_d3_lplu_state(struct em_hw *, boolean_t);
 static int32_tem_set_d0_lplu_state(struct em_hw *, boolean_t);
 @@ -5523,6 +5526,12 @@ em_init_eeprom_params(struct em_hw *hw)
   eecd = ~E1000_EECD_AUPDEN;
   E1000_WRITE_REG(hw, EECD, eecd);
   }
 + if (em_get_flash_presence_i210(hw) == FALSE) {
 + eeprom-type = em_eeprom_invm;
 + eeprom-word_size = INVM_SIZE;
 + eeprom-use_eerd = FALSE;
 + eeprom-use_eewr = FALSE;
 + }
   break;
   case em_80003es2lan:
   eeprom-type = em_eeprom_spi;
 @@ -5986,6 +5995,7 @@ em_read_eeprom(struct em_hw *hw, uint16_t offset, 
 uint16_t words,
* FW or other port software does not interrupt.
*/
   if (em_is_onboard_nvm_eeprom(hw) == TRUE 
 + em_get_flash_presence_i210(hw) == TRUE 
   hw-eeprom.use_eerd == FALSE) {
   /* Prepare the EEPROM for bit-bang reading */
   if (em_acquire_eeprom(hw) != E1000_SUCCESS)
 @@ -5998,6 +6008,11 @@ em_read_eeprom(struct em_hw *hw, uint16_t offset, 
 uint16_t words,
   /* ICH EEPROM access is done via the ICH flash controller */
   if (eeprom-type == em_eeprom_ich8)
   return em_read_eeprom_ich8(hw, offset, words, data);
 +
 + /* Some i210/i211 have a special OTP chip */
 + if (eeprom-type == em_eeprom_invm)
 + return em_read_invm_i210(hw, offset, words, data);
 +
   /*
* Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
* acquired the EEPROM at this point, so any returns should relase it
 @@ -6182,6 +6197,28 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw)
 }
 
 /**
 + * Check if flash device is detected.
 + *
 + * hw - Struct containing variables accessed by shared code
 + 
 */
 +boolean_t
 +em_get_flash_presence_i210(struct em_hw *hw)
 +{
 + uint32_t eecd;
 + DEBUGFUNC(em_get_flash_presence_i210);
 +
 + if (hw-mac_type != em_i210)
 + return TRUE;
 +
 + eecd = E1000_READ_REG(hw, EECD);
 +
 + if (eecd  E1000_EECD_FLUPD)
 + return TRUE;
 +
 + return FALSE;
 +}
 +
 +/**
  * Verifies that the EEPROM has a valid checksum
  *
  * hw - Struct containing variables accessed by shared code
 @@ -9730,6 +9767,84 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t 
 bank)
   return error;
 }
 
 +/**
 + * Reads 16-bit words from the OTP. Return error when the word is not
 + * stored in OTP.
 + *
 + * hw - Struct containing variables accessed by shared code
 + * offset - offset of word in the OTP to read
 + * data - 

Re: support em(4) i210/i211 OTP chips

2015-03-18 Thread Jonathan Gray
On Mon, Mar 09, 2015 at 07:32:45AM +0100, Patrick Wildt wrote:
 Hi,
 
 this diff adds support for a special configuration of i210/i211 chips.
 
 Those can have a OTP chip instead of the usual EEPROM, so this diff
 adds the infrastructure to read needed data from OTP and have it not
 bail out when there's no EEPROM.
 
 \Patrick

...

  
 +/**
 + * Reads 16-bit words from the OTP. Return error when the word is not
 + * stored in OTP.
 + *
 + * hw - Struct containing variables accessed by shared code
 + * offset - offset of word in the OTP to read
 + * data - word read from the OTP
 + * words - number of words to read
 + 
 */
 +STATIC int32_t
 +em_read_invm_i210(struct em_hw *hw, uint16_t offset, uint16_t words,
 +uint16_t *data)
 +{
 + int32_t  ret_val = E1000_SUCCESS;
 +
 + switch (offset)
 + {
 + case EEPROM_MAC_ADDRESS:
 + case EEPROM_MAC_ADDRESS_WORD1:
 + case EEPROM_MAC_ADDRESS_WORD2:
 + /* Generate random MAC address if there's none. */
 + ret_val = em_read_invm_word_i210(hw, offset, data);
 + if (ret_val != E1000_SUCCESS) {
 + *data = 0x;
 + ret_val = E1000_SUCCESS;
 + }
 + break;
 + case EEPROM_ID_LED_SETTINGS:
 + ret_val = em_read_invm_word_i210(hw, offset, data);
 + if (ret_val != E1000_SUCCESS) {
 + *data = ID_LED_RESERVED_;
 + ret_val = E1000_SUCCESS;
 + }
 + break;
 + }
 +
 + return ret_val;
 +}

Is there any value in adding the other offsets the Intel code has?

case NVM_INIT_CTRL_2(EEPROM_INIT_CONTROL2_REG)
case NVM_INIT_CTRL_4
case NVM_LED_1_CFG
case NVM_LED_0_2_CFG
case NVM_SUB_DEV_ID
case NVM_SUB_VEN_ID
case NVM_DEV_ID
case NVM_VEN_ID

Either way it seems there should be a default case, the Intel code
uses *data = NVM_RESERVED_WORD for that.

  
 +/* INVM Registers for i210 */
 +#define E1000_INVM_DATA_REG(reg) (0x12120 + 4*(reg))
 +#define E1000_82542_INVM_DATA_REG(reg)   E1000_INVM_DATA_REG(reg)

You can avoid having to add _82542_ defines by using
EM_READ_REG instead of E1000_READ_REG.



support em(4) i210/i211 OTP chips

2015-03-09 Thread Patrick Wildt
Hi,

this diff adds support for a special configuration of i210/i211 chips.

Those can have a OTP chip instead of the usual EEPROM, so this diff
adds the infrastructure to read needed data from OTP and have it not
bail out when there's no EEPROM.

\Patrick

diff --git a/sys/dev/pci/if_em.c b/sys/dev/pci/if_em.c
index 8717fa4..10cdc52 100644
--- sys/dev/pci/if_em.c
+++ sys/dev/pci/if_em.c
@@ -1775,7 +1775,8 @@ em_hardware_init(struct em_softc *sc)
sc-tx_fifo_head = 0;
 
/* Make sure we have a good EEPROM before we read from it */
-   if (em_validate_eeprom_checksum(sc-hw)  0) {
+   if (em_get_flash_presence_i210(sc-hw) 
+   em_validate_eeprom_checksum(sc-hw)  0) {
/*
 * Some PCIe parts fail the first check due to
 * the link being in sleep state, call it again,
@@ -1788,7 +1789,8 @@ em_hardware_init(struct em_softc *sc)
}
}
 
-   if (em_read_part_num(sc-hw, (sc-part_num))  0) {
+   if (em_get_flash_presence_i210(sc-hw) 
+   em_read_part_num(sc-hw, (sc-part_num))  0) {
printf(%s: EEPROM read error while reading part number\n,
   sc-sc_dv.dv_xname);
return (EIO);
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c
index 16cd3ee..4994c4d 100644
--- sys/dev/pci/if_em_hw.c
+++ sys/dev/pci/if_em_hw.c
@@ -113,6 +113,9 @@ static int32_t  em_read_eeprom_ich8(struct em_hw *, 
uint16_t, uint16_t,
uint16_t *);
 static int32_t em_write_eeprom_ich8(struct em_hw *, uint16_t, uint16_t,
uint16_t *);
+static int32_t em_read_invm_i210(struct em_hw *, uint16_t, uint16_t,
+   uint16_t *);
+static int32_t em_read_invm_word_i210(struct em_hw *, uint16_t, uint16_t *);
 static voidem_release_software_flag(struct em_hw *);
 static int32_t em_set_d3_lplu_state(struct em_hw *, boolean_t);
 static int32_t em_set_d0_lplu_state(struct em_hw *, boolean_t);
@@ -5523,6 +5526,12 @@ em_init_eeprom_params(struct em_hw *hw)
eecd = ~E1000_EECD_AUPDEN;
E1000_WRITE_REG(hw, EECD, eecd);
}
+   if (em_get_flash_presence_i210(hw) == FALSE) {
+   eeprom-type = em_eeprom_invm;
+   eeprom-word_size = INVM_SIZE;
+   eeprom-use_eerd = FALSE;
+   eeprom-use_eewr = FALSE;
+   }
break;
case em_80003es2lan:
eeprom-type = em_eeprom_spi;
@@ -5986,6 +5995,7 @@ em_read_eeprom(struct em_hw *hw, uint16_t offset, 
uint16_t words,
 * FW or other port software does not interrupt.
 */
if (em_is_onboard_nvm_eeprom(hw) == TRUE 
+   em_get_flash_presence_i210(hw) == TRUE 
hw-eeprom.use_eerd == FALSE) {
/* Prepare the EEPROM for bit-bang reading */
if (em_acquire_eeprom(hw) != E1000_SUCCESS)
@@ -5998,6 +6008,11 @@ em_read_eeprom(struct em_hw *hw, uint16_t offset, 
uint16_t words,
/* ICH EEPROM access is done via the ICH flash controller */
if (eeprom-type == em_eeprom_ich8)
return em_read_eeprom_ich8(hw, offset, words, data);
+
+   /* Some i210/i211 have a special OTP chip */
+   if (eeprom-type == em_eeprom_invm)
+   return em_read_invm_i210(hw, offset, words, data);
+
/*
 * Set up the SPI or Microwire EEPROM for bit-bang reading.  We have
 * acquired the EEPROM at this point, so any returns should relase it
@@ -6182,6 +6197,28 @@ em_is_onboard_nvm_eeprom(struct em_hw *hw)
 }
 
 /**
+ * Check if flash device is detected.
+ *
+ * hw - Struct containing variables accessed by shared code
+ */
+boolean_t
+em_get_flash_presence_i210(struct em_hw *hw)
+{
+   uint32_t eecd;
+   DEBUGFUNC(em_get_flash_presence_i210);
+
+   if (hw-mac_type != em_i210)
+   return TRUE;
+
+   eecd = E1000_READ_REG(hw, EECD);
+
+   if (eecd  E1000_EECD_FLUPD)
+   return TRUE;
+
+   return FALSE;
+}
+
+/**
  * Verifies that the EEPROM has a valid checksum
  *
  * hw - Struct containing variables accessed by shared code
@@ -9730,6 +9767,84 @@ em_erase_ich8_4k_segment(struct em_hw *hw, uint32_t bank)
return error;
 }
 
+/**
+ * Reads 16-bit words from the OTP. Return error when the word is not
+ * stored in OTP.
+ *
+ * hw - Struct containing variables accessed by shared code
+ * offset - offset of word in the OTP to read
+ * data - word read from the OTP
+ * words - number of words to read
+