[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