[U-Boot] [PATCH 2/2] usb: eth: smsc95xx: Add EEPROM access support
Alban Bedel
alban.bedel at avionic-design.de
Tue Oct 7 11:19:37 CEST 2014
Use the new ethernet eeprom API to allow the user to read/write the
EEPROM.
Change-Id: I21233b6ee805a75bd8a03ca12e22c41421b7629c
Signed-off-by: Alban Bedel <alban.bedel at avionic-design.de>
---
drivers/usb/eth/smsc95xx.c | 199 +++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 192 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index 6bca34d..eb29565 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -59,6 +59,8 @@
#define E2P_CMD 0x30
#define E2P_CMD_BUSY_ 0x80000000
+#define E2P_CMD_EWEN_ 0x20000000
+#define E2P_CMD_WRITE_ 0x30000000
#define E2P_CMD_READ_ 0x00000000
#define E2P_CMD_TIMEOUT_ 0x00000400
#define E2P_CMD_LOADED_ 0x00000200
@@ -146,6 +148,131 @@ struct smsc95xx_private {
int have_hwaddr; /* 1 if we have a hardware MAC address */
};
+#ifdef CONFIG_CMD_ETH_EEPROM
+static u8 eeprom_defaults[] = {
+ /* 0x00 */
+ 0xA5, /* Signature */
+ 0xFF, 0xFF, /* MAC bytes 0-1 */
+ 0xFF, 0xFF, /* MAC bytes 2-3 */
+ 0xFF, 0xFF, /* MAC bytes 4-5 */
+ 0x01, /* FS Polling Interval for Interrupt Endpoint */
+ 0x01, /* HS Polling Interval for Interrupt Endpoint */
+ 0x01, /* Configuration Flags */
+ 0x09, 0x04, /* Language ID */
+ 0x0a, /* Manufacturer ID String Descriptor Length (bytes) */
+ 0x2f, /* Manufacturer ID String Descriptor EEPROM Word Offset */
+ 0x10, /* Product Name String Descriptor Length (bytes) */
+ 0x34, /* Product Name String Descriptor EEPROM Word Offset */
+ /* 0x10 */
+ 0x12, /* Serial Number String Descriptor Length (bytes) */
+ 0x3c, /* Serial Number String Descriptor EEPROM Word Offset */
+ 0x08, /* Configuration String Descriptor Length (bytes) */
+ 0x45, /* Configuration String Descriptor Word Offset */
+ 0x08, /* Interface String Descriptor Length (bytes) */
+ 0x49, /* Interface String Descriptor Word Offset */
+ 0x12, /* Hi-Speed Device Descriptor Length (bytes) */
+ 0x1d, /* Hi-Speed Device Descriptor Word Offset */
+ 0x12, /* Hi-Speed Configuration and Interface Descriptor Length (bytes) */
+ 0x26, /* Hi-Speed Configuration and Interface Descriptor Word Offset */
+ 0x12, /* Full-Speed Device Descriptor Length (bytes) */
+ 0x1d, /* Full-Speed Device Descriptor Word Offset */
+ 0x12, /* Full-Speed Configuration and Interface Descriptor Length (bytes) */
+ 0x26, /* Full-Speed Configuration and Interface Descriptor Word Offset */
+ 0x00, 0x00, /* RESERVED */
+ /* 0x20 */
+ 0x24, 0x04, /* Vendor ID */
+ 0x14, 0x95, /* Product ID */
+ 0x00, 0x01, /* Device ID */
+ 0x9b, /* Config Data Byte 1 Register (CFG1) */
+ 0x18, /* Config Data Byte 2 Register (CFG2) */
+ 0x00, /* Config Data Byte 3 Register (CFG3) */
+ 0x32, /* Non-Removable Devices Register (NRD) */
+ 0x00, /* Port Disable (Self) Register (PDS) */
+ 0x00, /* Port Disable (Bus) Register (PDB) */
+ 0x01, /* Max Power (Self) Register (MAXPS) */
+ 0x00, /* Max Power (Bus) Register (MAXPB) */
+ 0x01, /* Hub Controller Max Current (Self) Register (HCMCS) */
+ 0x00, /* Hub Controller Max Current (Bus) Register (HCMCB) */
+ /* 0x30 */
+ 0x32, /* Power-on Time Register (PWRT) */
+ 0x00, /* Boost_Up Register (BOOSTUP) */
+ 0x00, /* Boost_5 Register (BOOST5) */
+ 0x00, /* Boost_4:2 Register (BOOST42) */
+ 0x00, /* RESERVED */
+ 0x00, /* Port Swap Register (PRTSP) */
+ 0x21, /* Port Remap 12 Register (PRTR12) */
+ 0x43, /* Port Remap 34 Register (PRTR34) */
+ 0x05, /* Port Remap 5 Register (PRTR5) */
+ 0x01, /* Status/Command Register (STCD) */
+ /* 0x3A - Device Descriptor */
+ 0x12, 0x01,
+ 0x00, 0x02,
+ 0xff, 0x00,
+ /* 0x40 */
+ 0xff, 0x40,
+ 0x24, 0x04,
+ 0x00, 0xec,
+ 0x00, 0x01,
+ 0x01, 0x02,
+ 0x03, 0x01,
+ /* 0x4C - Configuration and Interface Descriptor */
+ 0x09, 0x02,
+ 0x27, 0x00,
+ /* 0x50 */
+ 0x01, 0x01,
+ 0x04, 0xc0,
+ 0x00, 0x09,
+ 0x04, 0x00,
+ 0x00, 0x03,
+ 0xff, 0x00,
+ 0xff, 0x05,
+ /* 0x5E - Manufacturer ID String Descriptor */
+ 0x0a, 0x03,
+ /* 0x60 */
+ 0x53, 0x00, /* S */
+ 0x4d, 0x00, /* M */
+ 0x53, 0x00, /* S */
+ 0x43, 0x00, /* C */
+ /* 0x68 - Product Name String */
+ 0x10, 0x03,
+ 0x4c, 0x00, /* L */
+ 0x41, 0x00, /* A */
+ 0x4e, 0x00, /* N */
+ /* 0x70 */
+ 0x39, 0x00, /* 9 */
+ 0x35, 0x00, /* 5 */
+ 0x31, 0x00, /* 1 */
+ 0x34, 0x00, /* 5 */
+ /* 0x78 - Serial Number String Descriptor */
+ 0x12, 0x03,
+ 0x31, 0x00, /* 1 */
+ 0x32, 0x00, /* 2 */
+ 0x33, 0x00, /* 3 */
+ /* 0x80 */
+ 0x34, 0x00, /* 4 */
+ 0x35, 0x00, /* 5 */
+ 0x36, 0x00, /* 6 */
+ 0x37, 0x00, /* 7 */
+ 0x38, 0x00, /* 8 */
+ /* 0x8A - Configuration String Descriptor */
+ 0x08, 0x03,
+ 0x43, 0x00, /* C */
+ 0x66, 0x00, /* f */
+ /* 0x90 */
+ 0x67, 0x00, /* g */
+ /* 0x92 - Interface String Descriptor */
+ 0x08, 0x03,
+ 0x69, 0x00, /* i */
+ 0x2f, 0x00, /* / */
+ 0x66, 0x00, /* f */
+ /* 0x9A - END */
+ 0x00, 0x00,
+ 0x00, 0x00,
+ 0x00, 0x00,
+ /* 0xA0 */
+};
+#endif
+
/*
* Smsc95xx infrastructure commands
*/
@@ -285,9 +412,10 @@ static int smsc95xx_wait_eeprom(struct ueth_data *dev)
return 0;
}
-static int smsc95xx_read_eeprom(struct ueth_data *dev, u32 offset, u32 length,
- u8 *data)
+static int smsc95xx_read_eeprom(struct eth_device *eth, u32 offset, u32 length,
+ u8 *data)
{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
u32 val;
int i, ret;
@@ -310,6 +438,58 @@ static int smsc95xx_read_eeprom(struct ueth_data *dev, u32 offset, u32 length,
return 0;
}
+#ifdef CONFIG_CMD_ETH_EEPROM
+static int smsc95xx_write_eeprom(struct eth_device *eth, u32 offset, u32 length,
+ u8 *data)
+{
+ struct ueth_data *dev = (struct ueth_data *)eth->priv;
+ u32 val;
+ int i, ret;
+
+ ret = smsc95xx_eeprom_confirm_not_busy(dev);
+ if (ret)
+ return ret;
+
+ /* Issue write/erase enable command */
+ val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_;
+ ret = smsc95xx_write_reg(dev, E2P_CMD, val);
+ if (ret < 0)
+ return ret;
+
+ ret = smsc95xx_wait_eeprom(dev);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < length; i++) {
+ /* Fill data register */
+ val = data[i];
+ ret = smsc95xx_write_reg(dev, E2P_DATA, val);
+ if (ret < 0)
+ return ret;
+
+ /* Send "write" command */
+ val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ |
+ (offset & E2P_CMD_ADDR_);
+ ret = smsc95xx_write_reg(dev, E2P_CMD, val);
+ if (ret < 0)
+ return ret;
+
+ ret = smsc95xx_wait_eeprom(dev);
+ if (ret < 0)
+ return ret;
+
+ offset++;
+ }
+ return 0;
+}
+
+static int smsc95xx_defaults_eeprom(struct eth_device *eth)
+{
+ return smsc95xx_write_eeprom(eth, 0, sizeof(eeprom_defaults),
+ eeprom_defaults);
+}
+#endif
+
/*
* mii_nway_restart - restart NWay (autonegotiation) for this interface
*
@@ -349,12 +529,11 @@ static int smsc95xx_phy_initialize(struct ueth_data *dev)
return 0;
}
-static int smsc95xx_init_mac_address(struct eth_device *eth,
- struct ueth_data *dev)
+static int smsc95xx_init_mac_address(struct eth_device *eth)
{
/* try reading mac address from EEPROM */
- if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN,
- eth->enetaddr) == 0) {
+ if (smsc95xx_read_eeprom(eth, EEPROM_MAC_OFFSET, ETH_ALEN,
+ eth->enetaddr) == 0) {
if (is_valid_ether_addr(eth->enetaddr)) {
/* eeprom values are valid so use them */
debug("MAC address read from EEPROM\n");
@@ -507,7 +686,7 @@ static int smsc95xx_init(struct eth_device *eth, bd_t *bd)
debug("timeout waiting for PHY Reset\n");
return -1;
}
- if (!priv->have_hwaddr && smsc95xx_init_mac_address(eth, dev) == 0)
+ if (!priv->have_hwaddr && smsc95xx_init_mac_address(eth) == 0)
priv->have_hwaddr = 1;
if (!priv->have_hwaddr) {
puts("Error: SMSC95xx: No MAC address set - set usbethaddr\n");
@@ -894,6 +1073,12 @@ int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
eth->recv = smsc95xx_recv;
eth->halt = smsc95xx_halt;
eth->write_hwaddr = smsc95xx_write_hwaddr;
+#ifdef CONFIG_CMD_ETH_EEPROM
+ eth->eeprom_read = smsc95xx_read_eeprom;
+ eth->eeprom_write = smsc95xx_write_eeprom;
+ eth->eeprom_defaults = smsc95xx_defaults_eeprom;
+ eth->eeprom_mac_offset = EEPROM_MAC_OFFSET;
+#endif
eth->priv = ss;
return 1;
}
--
2.1.1
More information about the U-Boot
mailing list