From 1bf9c51be25c7ac110c804e40bb5d6eda6f7dda7 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Wed, 22 Nov 2017 11:22:31 +0100 Subject: net/e1000: provide device for accessing emulated eeprom MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This device uses e1000_read_eeprom to provide access to the emulated eeprom on e1000-igb. Only reading is implemented for now. Signed-off-by: Uwe Kleine-König Signed-off-by: Sascha Hauer --- drivers/net/e1000/e1000.h | 2 ++ drivers/net/e1000/eeprom.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'drivers/net/e1000') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index ac68e28276..1e2c5d7bc5 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -2161,6 +2161,8 @@ struct e1000_hw { int line; } invm; + struct cdev eepromcdev; + struct mtd_info mtd; uint32_t phy_id; diff --git a/drivers/net/e1000/eeprom.c b/drivers/net/e1000/eeprom.c index 5ee545d8fd..e5f8c9e271 100644 --- a/drivers/net/e1000/eeprom.c +++ b/drivers/net/e1000/eeprom.c @@ -1298,6 +1298,31 @@ static struct file_operations e1000_invm_ops = { .lseek = dev_lseek_default, }; +static ssize_t e1000_eeprom_cdev_read(struct cdev *cdev, void *buf, + size_t count, loff_t offset, unsigned long flags) +{ + struct e1000_hw *hw = container_of(cdev, struct e1000_hw, eepromcdev); + int32_t ret; + + /* + * The eeprom interface works on 16 bit words which gives a nice excuse + * for being lazy and not implementing unaligned reads. + */ + if (offset & 1 || count == 1) + return -EIO; + + ret = e1000_read_eeprom(hw, offset / 2, count / 2, buf); + if (ret) + return -EIO; + else + return (count / 2) * 2; +}; + +static struct file_operations e1000_eeprom_ops = { + .read = e1000_eeprom_cdev_read, + .lseek = dev_lseek_default, +}; + static int e1000_mtd_read_or_write(bool read, struct mtd_info *mtd, loff_t off, size_t len, size_t *retlen, u_char *buf) @@ -1438,6 +1463,15 @@ int e1000_register_eeprom(struct e1000_hw *hw) if (hw->mac_type == e1000_igb) { uint32_t eecd = e1000_read_reg(hw, E1000_EECD); + hw->eepromcdev.dev = hw->dev; + hw->eepromcdev.ops = &e1000_eeprom_ops; + hw->eepromcdev.name = xasprintf("e1000-eeprom%d", hw->dev->id); + hw->eepromcdev.size = 0x1000; + + ret = devfs_create(&hw->eepromcdev); + if (ret < 0) + return ret; + if (eecd & E1000_EECD_I210_FLASH_DETECTED) { hw->mtd.parent = hw->dev; hw->mtd.read = e1000_mtd_read; @@ -1458,11 +1492,18 @@ int e1000_register_eeprom(struct e1000_hw *hw) ret = add_mtd_device(&hw->mtd, "e1000-nor", DEVICE_ID_DYNAMIC); - if (ret) + if (ret) { + devfs_remove(&hw->eepromcdev); return ret; + } } ret = e1000_register_invm(hw); + if (ret < 0) { + if (eecd & E1000_EECD_I210_FLASH_DETECTED) + del_mtd_device(&hw->mtd); + devfs_remove(&hw->eepromcdev); + } } return ret; -- cgit v1.2.3