summaryrefslogtreecommitdiffstats
path: root/drivers/net/e1000
diff options
context:
space:
mode:
authorUwe Kleine-König <u.kleine-koenig@pengutronix.de>2017-11-22 11:22:29 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2017-11-24 10:06:14 +0100
commit761bed13abcb9a5108ef8bbceba77f6f4e61e8e3 (patch)
tree9cebb4e0844554345d155e60038a31dbd42deb1a /drivers/net/e1000
parent8c9f6705e5140260c479ee32e98ac95747e2ad1d (diff)
downloadbarebox-761bed13abcb9a5108ef8bbceba77f6f4e61e8e3.tar.gz
barebox-761bed13abcb9a5108ef8bbceba77f6f4e61e8e3.tar.xz
net/e1000: provide access to iNVM even if a flash is present
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@pengutronix.de> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/net/e1000')
-rw-r--r--drivers/net/e1000/e1000.h6
-rw-r--r--drivers/net/e1000/eeprom.c133
2 files changed, 72 insertions, 67 deletions
diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index f2da08b4d5..ac68e28276 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 9948a8c952..e5d1c5921f 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;