[PATCH 4/6] net/e1000: provide access to iNVM even if a flash is present

Uwe Kleine-König u.kleine-koenig at pengutronix.de
Wed Nov 22 02:22:29 PST 2017


An i210 (aka e1000_igb) supports two different non-volatile storages for
configuration. There is a built-in one-time programmable storage called
iNVM and an optional external SPI-Flash. If a flash is populated and
contains a valid configuration image the iNVM is not used (if I
understood the documentation correctly). Still the iNVM can be useful if
the flash is not configured. Also the iNVM contains manufacturing
identification information.

So it makes sense to provide the invm device even if a flash is present.

This patch also cleans up some confusion that suggests that invm is a
way to access the (simulated) eeprom structures and drops some unused
enum values.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig at pengutronix.de>
---
If you look at the diff ignoring whitespace changes (git diff -b) the patch
looks much prettier.

 drivers/net/e1000/e1000.h  |   6 +-
 drivers/net/e1000/eeprom.c | 133 ++++++++++++++++++++++++---------------------
 2 files changed, 72 insertions(+), 67 deletions(-)

diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index f2da08b4d5c1..ac68e28276c1 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -65,13 +65,9 @@ typedef enum {
 } e1000_media_type;
 
 typedef enum {
-	e1000_eeprom_uninitialized = 0,
 	e1000_eeprom_spi,
 	e1000_eeprom_microwire,
-	e1000_eeprom_flash,
-	e1000_eeprom_ich8,
-	e1000_eeprom_none, /* No NVM support */
-	e1000_eeprom_invm,
+	e1000_eeprom_flash, /* access via EERD */
 	e1000_num_eeprom_types
 } e1000_eeprom_type;
 
diff --git a/drivers/net/e1000/eeprom.c b/drivers/net/e1000/eeprom.c
index 9948a8c95275..e5d1c5921f5e 100644
--- a/drivers/net/e1000/eeprom.c
+++ b/drivers/net/e1000/eeprom.c
@@ -493,13 +493,11 @@ int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
 					 "limiting access to first 4KB\n");
 			}
 
-			eeprom->type = e1000_eeprom_flash;
 			eeprom->acquire = e1000_acquire_eeprom_flash;
 			eeprom->release = e1000_release_eeprom_flash;
-		} else {
-			eeprom->type = e1000_eeprom_invm;
 		}
 
+		eeprom->type = e1000_eeprom_flash;
 		eeprom->read = e1000_read_eeprom_eerd;
 		break;
 
@@ -507,8 +505,7 @@ int32_t e1000_init_eeprom_params(struct e1000_hw *hw)
 		break;
 	}
 
-	if (eeprom->type == e1000_eeprom_spi ||
-	    eeprom->type == e1000_eeprom_invm) {
+	if (eeprom->type == e1000_eeprom_spi) {
 		/* eeprom_size will be an enum [0..8] that maps
 		 * to eeprom sizes 128B to
 		 * 32KB (incremented by powers of 2).
@@ -1385,75 +1382,87 @@ fail:
 	return ret;
 }
 
-int e1000_register_eeprom(struct e1000_hw *hw)
+int e1000_register_invm(struct e1000_hw *hw)
 {
-	int ret = E1000_SUCCESS;
+	int ret;
 	u16 word;
 	struct param_d *p;
 
-	struct e1000_eeprom_info *eeprom = &hw->eeprom;
+	ret = e1000_read_eeprom(hw, 0x0a, 1, &word);
+	if (ret < 0)
+		return ret;
 
-	switch (eeprom->type) {
-	case e1000_eeprom_invm:
-		ret = e1000_read_eeprom(hw, 0x0A, 1, &word);
-		if (ret < 0)
-			return ret;
+	if (word & (1 << 15))
+		dev_warn(hw->dev, "iNVM lockout mechanism is active\n");
 
-		if (word & (1 << 15))
-			dev_warn(hw->dev, "iNVM lockout mechanism is active\n");
+	hw->invm.cdev.dev = hw->dev;
+	hw->invm.cdev.ops = &e1000_invm_ops;
+	hw->invm.cdev.priv = hw;
+	hw->invm.cdev.name = xasprintf("e1000-invm%d", hw->dev->id);
+	hw->invm.cdev.size = 32 * E1000_INVM_DATA_MAX_N;
 
-		hw->invm.cdev.dev = hw->dev;
-		hw->invm.cdev.ops = &e1000_invm_ops;
-		hw->invm.cdev.priv = hw;
-		hw->invm.cdev.name = xasprintf("e1000-invm%d", hw->dev->id);
-		hw->invm.cdev.size = 32 * E1000_INVM_DATA_MAX_N;
+	ret = devfs_create(&hw->invm.cdev);
+	if (ret < 0)
+		return ret;
 
-		ret = devfs_create(&hw->invm.cdev);
-		if (ret < 0)
-			break;
+	strcpy(hw->invm.dev.name, "invm");
+	hw->invm.dev.parent = hw->dev;
+	ret = register_device(&hw->invm.dev);
+	if (ret < 0) {
+		devfs_remove(&hw->invm.cdev);
+		return ret;
+	}
 
-		strcpy(hw->invm.dev.name, "invm");
-		hw->invm.dev.parent = hw->dev;
-		ret = register_device(&hw->invm.dev);
-		if (ret < 0) {
-			devfs_remove(&hw->invm.cdev);
-			break;
-		}
+	p = dev_add_param_int(&hw->invm.dev, "lock", e1000_invm_set_lock,
+			      NULL, &hw->invm.line, "%u", hw);
+	if (IS_ERR(p)) {
+		unregister_device(&hw->invm.dev);
+		devfs_remove(&hw->invm.cdev);
+		ret = PTR_ERR(p);
+	}
 
-		p = dev_add_param_int(&hw->invm.dev, "lock", e1000_invm_set_lock,
-				      NULL, &hw->invm.line, "%u", hw);
-		if (IS_ERR(p)) {
-			unregister_device(&hw->invm.dev);
-			devfs_remove(&hw->invm.cdev);
-			break;
+	return ret;
+}
+
+/*
+ * This function has a wrong name for historic reasons, it doesn't add an
+ * eeprom, but the flash (if available) that is used to simulate the eeprom.
+ * Also a device that represents the invm is registered here (if available).
+ */
+int e1000_register_eeprom(struct e1000_hw *hw)
+{
+	int ret = E1000_SUCCESS;
+
+	struct e1000_eeprom_info *eeprom = &hw->eeprom;
+
+	if (hw->mac_type == e1000_igb) {
+		uint32_t eecd = e1000_read_reg(hw, E1000_EECD);
+
+		if (eecd & E1000_EECD_I210_FLASH_DETECTED) {
+			hw->mtd.parent = hw->dev;
+			hw->mtd.read = e1000_mtd_read;
+			hw->mtd.write = e1000_mtd_write;
+			hw->mtd.erase = e1000_mtd_erase;
+			hw->mtd.size = eeprom->word_size * 2;
+			hw->mtd.writesize = 1;
+			hw->mtd.subpage_sft = 0;
+
+			hw->mtd.eraseregions = xzalloc(sizeof(struct mtd_erase_region_info));
+			hw->mtd.erasesize = SZ_4K;
+			hw->mtd.eraseregions[0].erasesize = SZ_4K;
+			hw->mtd.eraseregions[0].numblocks = hw->mtd.size / SZ_4K;
+			hw->mtd.numeraseregions = 1;
+
+			hw->mtd.flags = MTD_CAP_NORFLASH;
+			hw->mtd.type = MTD_NORFLASH;
+
+			ret = add_mtd_device(&hw->mtd, "e1000-nor",
+					     DEVICE_ID_DYNAMIC);
+			if (ret)
+				return ret;
 		}
-		break;
-	case e1000_eeprom_flash:
-		if (hw->mac_type != e1000_igb)
-			break;
 
-		hw->mtd.parent = hw->dev;
-		hw->mtd.read = e1000_mtd_read;
-		hw->mtd.write = e1000_mtd_write;
-		hw->mtd.erase = e1000_mtd_erase;
-		hw->mtd.size = eeprom->word_size * 2;
-		hw->mtd.writesize = 1;
-		hw->mtd.subpage_sft = 0;
-
-		hw->mtd.eraseregions = xzalloc(sizeof(struct mtd_erase_region_info));
-		hw->mtd.erasesize = SZ_4K;
-		hw->mtd.eraseregions[0].erasesize = SZ_4K;
-		hw->mtd.eraseregions[0].numblocks = hw->mtd.size / SZ_4K;
-		hw->mtd.numeraseregions = 1;
-
-		hw->mtd.flags = MTD_CAP_NORFLASH;
-		hw->mtd.type = MTD_NORFLASH;
-
-		ret = add_mtd_device(&hw->mtd, "e1000-nor",
-				     DEVICE_ID_DYNAMIC);
-		break;
-	default:
-		break;
+		ret = e1000_register_invm(hw);
 	}
 
 	return ret;
-- 
2.11.0




More information about the barebox mailing list