[U-Boot] [PATCH 10/20] net: smsc95xx: Add driver-model support

Simon Glass sjg at chromium.org
Wed Jul 8 04:53:42 CEST 2015


Add support for driver model, so that CONFIG_DM_ETH can be defined and used
with this driver.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 drivers/usb/eth/smsc95xx.c | 142 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 142 insertions(+)

diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c
index b0c610d..1dcd088 100644
--- a/drivers/usb/eth/smsc95xx.c
+++ b/drivers/usb/eth/smsc95xx.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2015 Google, Inc
  * Copyright (c) 2011 The Chromium OS Authors.
  * Copyright (C) 2009 NVIDIA, Corporation
  * Copyright (C) 2007-2008 SMSC (Steve Glendinning)
@@ -7,6 +8,7 @@
  */
 
 #include <common.h>
+#include <dm.h>
 #include <errno.h>
 #include <malloc.h>
 #include <usb.h>
@@ -137,11 +139,16 @@
 
 #define TURBO_MODE
 
+#ifndef CONFIG_DM_ETH
 /* local vars */
 static int curr_eth_dev; /* index for name of next device detected */
+#endif
 
 /* driver private */
 struct smsc95xx_private {
+#ifdef CONFIG_DM_ETH
+	struct ueth_data ueth;
+#endif
 	size_t rx_urb_size;  /* maximum USB URB size */
 	u32 mac_cr;  /* MAC control register value */
 	int have_hwaddr;  /* 1 if we have a hardware MAC address */
@@ -714,6 +721,7 @@ static int smsc95xx_send_common(struct ueth_data *dev, void *packet, int length)
 	return err;
 }
 
+#ifndef CONFIG_DM_ETH
 /*
  * Smsc95xx callbacks
  */
@@ -931,3 +939,137 @@ int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
 	eth->priv = ss;
 	return 1;
 }
+#endif /* !CONFIG_DM_ETH */
+
+#ifdef CONFIG_DM_ETH
+static int smsc95xx_eth_start(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parentdata(dev);
+	struct smsc95xx_private *priv = dev_get_priv(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+
+	/* Driver-model Ethernet ensures we have this */
+	priv->have_hwaddr = 1;
+
+	return smsc95xx_init_common(udev, &priv->ueth, priv, pdata->enetaddr);
+}
+
+void smsc95xx_eth_stop(struct udevice *dev)
+{
+	debug("** %s()\n", __func__);
+}
+
+int smsc95xx_eth_send(struct udevice *dev, void *packet, int length)
+{
+	struct smsc95xx_private *priv = dev_get_priv(dev);
+
+	return smsc95xx_send_common(&priv->ueth, packet, length);
+}
+
+int smsc95xx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+	struct smsc95xx_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+	uint8_t *ptr;
+	int ret, len;
+	u32 packet_len;
+
+	len = usb_ether_get_rx_bytes(ueth, &ptr);
+	debug("%s: first try, len=%d\n", __func__, len);
+	if (!len) {
+		if (!(flags & ETH_RECV_CHECK_DEVICE))
+			return -EAGAIN;
+		ret = usb_ether_receive(ueth, RX_URB_SIZE);
+		if (ret == -EAGAIN)
+			return ret;
+
+		len = usb_ether_get_rx_bytes(ueth, &ptr);
+		debug("%s: second try, len=%d\n", __func__, len);
+	}
+
+	/*
+	 * 1st 4 bytes contain the length of the actual data plus error info.
+	 * Extract data length.
+	 */
+	if (len < sizeof(packet_len)) {
+		debug("Rx: incomplete packet length\n");
+		goto err;
+	}
+	memcpy(&packet_len, ptr, sizeof(packet_len));
+	le32_to_cpus(&packet_len);
+	if (packet_len & RX_STS_ES_) {
+		debug("Rx: Error header=%#x", packet_len);
+		goto err;
+	}
+	packet_len = ((packet_len & RX_STS_FL_) >> 16);
+
+	if (packet_len > len - sizeof(packet_len)) {
+		debug("Rx: too large packet: %d\n", packet_len);
+		goto err;
+	}
+
+	*packetp = ptr + sizeof(packet_len);
+	return packet_len;
+
+err:
+	usb_ether_advance_rxbuf(ueth, -1);
+	return -EINVAL;
+}
+
+static int smsc95xx_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
+{
+	struct smsc95xx_private *priv = dev_get_priv(dev);
+
+	packet_len = ALIGN(packet_len, 4);
+	usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
+
+	return 0;
+}
+
+int smsc95xx_write_hwaddr(struct udevice *dev)
+{
+	struct usb_device *udev = dev_get_parentdata(dev);
+	struct eth_pdata *pdata = dev_get_platdata(dev);
+	struct smsc95xx_private *priv = dev_get_priv(dev);
+
+	return smsc95xx_write_hwaddr_common(udev, priv, pdata->enetaddr);
+}
+
+static int smsc95xx_eth_probe(struct udevice *dev)
+{
+	struct smsc95xx_private *priv = dev_get_priv(dev);
+	struct ueth_data *ueth = &priv->ueth;
+
+	return usb_ether_register(dev, ueth, RX_URB_SIZE);
+}
+
+static const struct eth_ops smsc95xx_eth_ops = {
+	.start	= smsc95xx_eth_start,
+	.send	= smsc95xx_eth_send,
+	.recv	= smsc95xx_eth_recv,
+	.free_pkt = smsc95xx_free_pkt,
+	.stop	= smsc95xx_eth_stop,
+	.write_hwaddr = smsc95xx_write_hwaddr,
+};
+
+U_BOOT_DRIVER(smsc95xx_eth) = {
+	.name	= "smsc95xx_eth",
+	.id	= UCLASS_ETH,
+	.probe = smsc95xx_eth_probe,
+	.ops	= &smsc95xx_eth_ops,
+	.priv_auto_alloc_size = sizeof(struct smsc95xx_private),
+	.platdata_auto_alloc_size = sizeof(struct eth_pdata),
+};
+
+static const struct usb_device_id smsc95xx_eth_id_table[] = {
+	{ USB_DEVICE(0x05ac, 0x1402) },
+	{ USB_DEVICE(0x0424, 0xec00) },	/* LAN9512/LAN9514 Ethernet */
+	{ USB_DEVICE(0x0424, 0x9500) },	/* LAN9500 Ethernet */
+	{ USB_DEVICE(0x0424, 0x9730) },	/* LAN9730 Ethernet (HSIC) */
+	{ USB_DEVICE(0x0424, 0x9900) },	/* SMSC9500 USB Ethernet (SAL10) */
+	{ USB_DEVICE(0x0424, 0x9e00) },	/* LAN9500A Ethernet */
+	{ }		/* Terminating entry */
+};
+
+U_BOOT_USB_DEVICE(smsc95xx_eth, smsc95xx_eth_id_table);
+#endif
-- 
2.4.3.573.g4eafbef



More information about the U-Boot mailing list