*/
#include <common.h>
-#include <asm/errno.h>
+#include <console.h>
+#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/usb/ch9.h>
#include <linux/usb/cdc.h>
#include <linux/usb/gadget.h>
#include <net.h>
+#include <usb.h>
#include <malloc.h>
+#include <memalign.h>
#include <linux/ctype.h>
#include "gadget_chips.h"
#include "rndis.h"
+#include <dm.h>
+#include <dm/lists.h>
+#include <dm/uclass-internal.h>
+#include <dm/device-internal.h>
+
#define USB_NET_NAME "usb_ether"
#define atomic_read
/* Based on linux 2.6.27 version */
#define DRIVER_VERSION "May Day 2005"
-static const char shortname[] = "ether";
static const char driver_desc[] = DRIVER_DESC;
#define RX_EXTRA 20 /* guard against rx overflows */
struct usb_gadget *gadget;
struct usb_request *req; /* for control responses */
struct usb_request *stat_req; /* for cdc & rndis status */
+#ifdef CONFIG_DM_USB
+ struct udevice *usb_udev;
+#endif
u8 config;
struct usb_ep *in_ep, *out_ep, *status_ep;
struct usb_request *tx_req, *rx_req;
+#ifndef CONFIG_DM_ETH
struct eth_device *net;
+#else
+ struct udevice *net;
+#endif
struct net_device_stats stats;
unsigned int tx_qlen;
*/
/*-------------------------------------------------------------------------*/
-static struct eth_dev l_ethdev;
-static struct eth_device l_netdev;
-static struct usb_gadget_driver eth_driver;
+struct ether_priv {
+ struct eth_dev ethdev;
+#ifndef CONFIG_DM_ETH
+ struct eth_device netdev;
+#else
+ struct udevice *netdev;
+#endif
+ struct usb_gadget_driver eth_driver;
+};
+
+struct ether_priv eth_priv;
+struct ether_priv *l_priv = ð_priv;
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_USBNET_MANUFACTURER)
static char *iManufacturer = CONFIG_USBNET_MANUFACTURER;
#else
-static char *iManufacturer = "U-boot";
+static char *iManufacturer = "U-Boot";
#endif
/* These probably need to be configurable. */
* can't really use its struct. All we do here is say that we're using
* the submode of "SAFE" which directly matches the CDC Subset.
*/
+#ifdef CONFIG_USB_ETH_SUBSET
static const u8 mdlm_detail_desc[] = {
6,
USB_DT_CS_INTERFACE,
0, /* network control capabilities (none) */
0, /* network data capabilities ("raw" encapsulation) */
};
+#endif
#endif
event->bNotificationType, value);
if (event->bNotificationType ==
USB_CDC_NOTIFY_SPEED_CHANGE) {
- l_ethdev.network_started = 1;
+ dev->network_started = 1;
printf("USB network up!\n");
}
}
* that network is working. So we signalize it
* here.
*/
- l_ethdev.network_started = 1;
+ dev->network_started = 1;
debug("USB network up!\n");
goto done_set_intf;
}
debug("rndis control ack complete --> %d, %d/%d\n",
req->status, req->actual, req->length);
- if (!l_ethdev.network_started) {
+ if (!dev->network_started) {
if (rndis_get_state(dev->rndis_config)
== RNDIS_DATA_INITIALIZED) {
- l_ethdev.network_started = 1;
+ dev->network_started = 1;
printf("USB RNDIS network up!\n");
}
}
static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32))));
+#ifndef CONFIG_DM_ETH
static int rndis_control_ack(struct eth_device *net)
+#else
+static int rndis_control_ack(struct udevice *net)
+#endif
{
- struct eth_dev *dev = &l_ethdev;
+ struct ether_priv *priv = (struct ether_priv *)net->priv;
+ struct eth_dev *dev = &priv->ethdev;
int length;
struct usb_request *resp = dev->stat_req;
static int eth_bind(struct usb_gadget *gadget)
{
- struct eth_dev *dev = &l_ethdev;
+ struct eth_dev *dev = &l_priv->ethdev;
u8 cdc = 1, zlp = 1, rndis = 1;
struct usb_ep *in_ep, *out_ep, *status_ep = NULL;
int status = -ENOMEM;
int gcnum;
u8 tmp[7];
+#ifdef CONFIG_DM_ETH
+ struct eth_pdata *pdata = dev_get_platdata(l_priv->netdev);
+#endif
/* these flags are only ever cleared; compiler take note */
#ifndef CONFIG_USB_ETH_CDC
/* network device setup */
- dev->net = &l_netdev;
+#ifndef CONFIG_DM_ETH
+ dev->net = &l_priv->netdev;
+#else
+ dev->net = l_priv->netdev;
+#endif
dev->cdc = cdc;
dev->zlp = zlp;
dev->out_ep = out_ep;
dev->status_ep = status_ep;
+ memset(tmp, 0, sizeof(tmp));
/*
* Module params for these addresses should come from ID proms.
* The host side address is used with CDC and RNDIS, and commonly
* host side code for the SAFE thing cares -- its original BLAN
* thing didn't, Sharp never assigned those addresses on Zaurii.
*/
+#ifndef CONFIG_DM_ETH
get_ether_addr(dev_addr, dev->net->enetaddr);
-
- memset(tmp, 0, sizeof(tmp));
memcpy(tmp, dev->net->enetaddr, sizeof(dev->net->enetaddr));
+#else
+ get_ether_addr(dev_addr, pdata->enetaddr);
+ memcpy(tmp, pdata->enetaddr, sizeof(pdata->enetaddr));
+#endif
get_ether_addr(host_addr, dev->host_mac);
status_ep ? " STATUS " : "",
status_ep ? status_ep->name : ""
);
- printf("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- dev->net->enetaddr[0], dev->net->enetaddr[1],
- dev->net->enetaddr[2], dev->net->enetaddr[3],
- dev->net->enetaddr[4], dev->net->enetaddr[5]);
+#ifndef CONFIG_DM_ETH
+ printf("MAC %pM\n", dev->net->enetaddr);
+#else
+ printf("MAC %pM\n", pdata->enetaddr);
+#endif
if (cdc || rndis)
printf("HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
/*-------------------------------------------------------------------------*/
-static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
+#ifdef CONFIG_DM_USB
+int dm_usb_init(struct eth_dev *e_dev)
{
- struct eth_dev *dev = &l_ethdev;
+ struct udevice *dev = NULL;
+ int ret;
+
+ ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev);
+ if (!dev || ret) {
+ error("No USB device found\n");
+ return -ENODEV;
+ }
+
+ e_dev->usb_udev = dev;
+
+ return ret;
+}
+#endif
+
+static int _usb_eth_init(struct ether_priv *priv)
+{
+ struct eth_dev *dev = &priv->ethdev;
struct usb_gadget *gadget;
unsigned long ts;
unsigned long timeout = USB_CONNECT_TIMEOUT;
- if (!netdev) {
- error("received NULL ptr");
- goto fail;
+#ifdef CONFIG_DM_USB
+ if (dm_usb_init(dev)) {
+ error("USB ether not found\n");
+ return -ENODEV;
}
+#else
+ board_usb_init(0, USB_INIT_DEVICE);
+#endif
/* Configure default mac-addresses for the USB ethernet device */
#ifdef CONFIG_USBNET_DEV_ADDR
goto fail;
}
- if (usb_gadget_register_driver(ð_driver) < 0)
+ priv->eth_driver.speed = DEVSPEED;
+ priv->eth_driver.bind = eth_bind;
+ priv->eth_driver.unbind = eth_unbind;
+ priv->eth_driver.setup = eth_setup;
+ priv->eth_driver.reset = eth_disconnect;
+ priv->eth_driver.disconnect = eth_disconnect;
+ priv->eth_driver.suspend = eth_suspend;
+ priv->eth_driver.resume = eth_resume;
+ if (usb_gadget_register_driver(&priv->eth_driver) < 0)
goto fail;
dev->network_started = 0;
timeout = simple_strtoul(getenv("cdc_connect_timeout"),
NULL, 10) * CONFIG_SYS_HZ;
ts = get_timer(0);
- while (!l_ethdev.network_started) {
+ while (!dev->network_started) {
/* Handle control-c and timeouts */
if (ctrlc() || (get_timer(ts) > timeout)) {
error("The remote end did not respond in time.");
return -1;
}
-static int usb_eth_send(struct eth_device *netdev, void *packet, int length)
+static int _usb_eth_send(struct ether_priv *priv, void *packet, int length)
{
int retval;
void *rndis_pkt = NULL;
- struct eth_dev *dev = &l_ethdev;
+ struct eth_dev *dev = &priv->ethdev;
struct usb_request *req = dev->tx_req;
unsigned long ts;
unsigned long timeout = USB_CONNECT_TIMEOUT;
return -ENOMEM;
}
-static int usb_eth_recv(struct eth_device *netdev)
+static int _usb_eth_recv(struct ether_priv *priv)
{
- struct eth_dev *dev = &l_ethdev;
-
usb_gadget_handle_interrupts(0);
- if (packet_received) {
- debug("%s: packet received\n", __func__);
- if (dev->rx_req) {
- net_process_received_packet(net_rx_packets[0],
- dev->rx_req->length);
- packet_received = 0;
-
- rx_submit(dev, dev->rx_req, 0);
- } else
- error("dev->rx_req invalid");
- }
return 0;
}
-void usb_eth_halt(struct eth_device *netdev)
+void _usb_eth_halt(struct ether_priv *priv)
{
- struct eth_dev *dev = &l_ethdev;
-
- if (!netdev) {
- error("received NULL ptr");
- return;
- }
+ struct eth_dev *dev = &priv->ethdev;
/* If the gadget not registered, simple return */
if (!dev->gadget)
dev->network_started = 0;
}
- usb_gadget_unregister_driver(ð_driver);
+ usb_gadget_unregister_driver(&priv->eth_driver);
+#ifndef CONFIG_DM_USB
+ board_usb_cleanup(0, USB_INIT_DEVICE);
+#endif
}
-static struct usb_gadget_driver eth_driver = {
- .speed = DEVSPEED,
+#ifndef CONFIG_DM_ETH
+static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
+{
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
- .bind = eth_bind,
- .unbind = eth_unbind,
+ return _usb_eth_init(priv);
+}
- .setup = eth_setup,
- .disconnect = eth_disconnect,
+static int usb_eth_send(struct eth_device *netdev, void *packet, int length)
+{
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
- .suspend = eth_suspend,
- .resume = eth_resume,
-};
+ return _usb_eth_send(priv, packet, length);
+}
+
+static int usb_eth_recv(struct eth_device *netdev)
+{
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
+ struct eth_dev *dev = &priv->ethdev;
+ int ret;
+
+ ret = _usb_eth_recv(priv);
+ if (ret) {
+ error("error packet receive\n");
+ return ret;
+ }
+
+ if (!packet_received)
+ return 0;
+
+ if (dev->rx_req) {
+ net_process_received_packet(net_rx_packets[0],
+ dev->rx_req->length);
+ } else {
+ error("dev->rx_req invalid");
+ }
+ packet_received = 0;
+ rx_submit(dev, dev->rx_req, 0);
+
+ return 0;
+}
+
+void usb_eth_halt(struct eth_device *netdev)
+{
+ struct ether_priv *priv = (struct ether_priv *)netdev->priv;
+
+ _usb_eth_halt(priv);
+}
int usb_eth_initialize(bd_t *bi)
{
- struct eth_device *netdev = &l_netdev;
+ struct eth_device *netdev = &l_priv->netdev;
strlcpy(netdev->name, USB_NET_NAME, sizeof(netdev->name));
netdev->send = usb_eth_send;
netdev->recv = usb_eth_recv;
netdev->halt = usb_eth_halt;
+ netdev->priv = l_priv;
#ifdef CONFIG_MCAST_TFTP
#error not supported
eth_register(netdev);
return 0;
}
+#else
+static int usb_eth_start(struct udevice *dev)
+{
+ struct ether_priv *priv = dev_get_priv(dev);
+
+ return _usb_eth_init(priv);
+}
+
+static int usb_eth_send(struct udevice *dev, void *packet, int length)
+{
+ struct ether_priv *priv = dev_get_priv(dev);
+
+ return _usb_eth_send(priv, packet, length);
+}
+
+static int usb_eth_recv(struct udevice *dev, int flags, uchar **packetp)
+{
+ struct ether_priv *priv = dev_get_priv(dev);
+ struct eth_dev *ethdev = &priv->ethdev;
+ int ret;
+
+ ret = _usb_eth_recv(priv);
+ if (ret) {
+ error("error packet receive\n");
+ return ret;
+ }
+
+ if (packet_received) {
+ if (ethdev->rx_req) {
+ *packetp = (uchar *)net_rx_packets[0];
+ return ethdev->rx_req->length;
+ } else {
+ error("dev->rx_req invalid");
+ return -EFAULT;
+ }
+ }
+
+ return -EAGAIN;
+}
+
+static int usb_eth_free_pkt(struct udevice *dev, uchar *packet,
+ int length)
+{
+ struct ether_priv *priv = dev_get_priv(dev);
+ struct eth_dev *ethdev = &priv->ethdev;
+
+ packet_received = 0;
+
+ return rx_submit(ethdev, ethdev->rx_req, 0);
+}
+
+static void usb_eth_stop(struct udevice *dev)
+{
+ struct ether_priv *priv = dev_get_priv(dev);
+
+ _usb_eth_halt(priv);
+}
+
+static int usb_eth_probe(struct udevice *dev)
+{
+ struct ether_priv *priv = dev_get_priv(dev);
+ struct eth_pdata *pdata = dev_get_platdata(dev);
+
+ priv->netdev = dev;
+ l_priv = priv;
+
+ get_ether_addr(CONFIG_USBNET_DEVADDR, pdata->enetaddr);
+ eth_setenv_enetaddr("usbnet_devaddr", pdata->enetaddr);
+
+ return 0;
+}
+
+static const struct eth_ops usb_eth_ops = {
+ .start = usb_eth_start,
+ .send = usb_eth_send,
+ .recv = usb_eth_recv,
+ .free_pkt = usb_eth_free_pkt,
+ .stop = usb_eth_stop,
+};
+
+int usb_ether_init(void)
+{
+ struct udevice *dev;
+ struct udevice *usb_dev;
+ int ret;
+
+ ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev);
+ if (!usb_dev || ret) {
+ error("No USB device found\n");
+ return ret;
+ }
+
+ ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", &dev);
+ if (!dev || ret) {
+ error("usb - not able to bind usb_ether device\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+U_BOOT_DRIVER(eth_usb) = {
+ .name = "usb_ether",
+ .id = UCLASS_ETH,
+ .probe = usb_eth_probe,
+ .ops = &usb_eth_ops,
+ .priv_auto_alloc_size = sizeof(struct ether_priv),
+ .platdata_auto_alloc_size = sizeof(struct eth_pdata),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};
+#endif /* CONFIG_DM_ETH */