"Das U-Boot" Source Tree
at master 136 lines 3.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2011 The Chromium OS Authors. 4 */ 5 6#include <dm.h> 7#include <errno.h> 8#include <log.h> 9#include <malloc.h> 10#include <net.h> 11#include <usb.h> 12#include <asm/cache.h> 13#include <dm/device-internal.h> 14 15#include "usb_ether.h" 16 17#define USB_BULK_RECV_TIMEOUT 500 18 19int usb_ether_register(struct udevice *dev, struct ueth_data *ueth, int rxsize) 20{ 21 struct usb_device *udev = dev_get_parent_priv(dev); 22 struct usb_interface_descriptor *iface_desc; 23 bool ep_in_found = false, ep_out_found = false; 24 struct usb_interface *iface; 25 const int ifnum = 0; /* Always use interface 0 */ 26 int ret, i; 27 28 iface = &udev->config.if_desc[ifnum]; 29 iface_desc = &udev->config.if_desc[ifnum].desc; 30 31 /* Initialize the ueth_data structure with some useful info */ 32 ueth->ifnum = ifnum; 33 ueth->subclass = iface_desc->bInterfaceSubClass; 34 ueth->protocol = iface_desc->bInterfaceProtocol; 35 36 /* 37 * We are expecting a minimum of 3 endpoints - in, out (bulk), and int. 38 * We will ignore any others. 39 */ 40 for (i = 0; i < iface_desc->bNumEndpoints; i++) { 41 int ep_addr = iface->ep_desc[i].bEndpointAddress; 42 43 /* is it an BULK endpoint? */ 44 if ((iface->ep_desc[i].bmAttributes & 45 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { 46 if (ep_addr & USB_DIR_IN && !ep_in_found) { 47 ueth->ep_in = ep_addr & 48 USB_ENDPOINT_NUMBER_MASK; 49 ep_in_found = true; 50 } else if (!(ep_addr & USB_DIR_IN) && !ep_out_found) { 51 ueth->ep_out = ep_addr & 52 USB_ENDPOINT_NUMBER_MASK; 53 ep_out_found = true; 54 } 55 } 56 57 /* is it an interrupt endpoint? */ 58 if ((iface->ep_desc[i].bmAttributes & 59 USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) { 60 ueth->ep_int = iface->ep_desc[i].bEndpointAddress & 61 USB_ENDPOINT_NUMBER_MASK; 62 ueth->irqinterval = iface->ep_desc[i].bInterval; 63 } 64 } 65 debug("Endpoints In %d Out %d Int %d\n", ueth->ep_in, ueth->ep_out, 66 ueth->ep_int); 67 68 /* Do some basic sanity checks, and bail if we find a problem */ 69 if (!ueth->ep_in || !ueth->ep_out || !ueth->ep_int) { 70 debug("%s: %s: Cannot find endpoints\n", __func__, dev->name); 71 return -ENXIO; 72 } 73 74 ueth->rxsize = rxsize; 75 ueth->rxbuf = memalign(ARCH_DMA_MINALIGN, rxsize); 76 if (!ueth->rxbuf) 77 return -ENOMEM; 78 79 ret = usb_set_interface(udev, iface_desc->bInterfaceNumber, ifnum); 80 if (ret) { 81 debug("%s: %s: Cannot set interface: %d\n", __func__, dev->name, 82 ret); 83 return ret; 84 } 85 ueth->pusb_dev = udev; 86 87 return 0; 88} 89 90int usb_ether_deregister(struct ueth_data *ueth) 91{ 92 return 0; 93} 94 95int usb_ether_receive(struct ueth_data *ueth, int rxsize) 96{ 97 int actual_len; 98 int ret; 99 100 if (rxsize > ueth->rxsize) 101 return -EINVAL; 102 ret = usb_bulk_msg(ueth->pusb_dev, 103 usb_rcvbulkpipe(ueth->pusb_dev, ueth->ep_in), 104 ueth->rxbuf, rxsize, &actual_len, 105 USB_BULK_RECV_TIMEOUT); 106 debug("Rx: len = %u, actual = %u, err = %d\n", rxsize, actual_len, ret); 107 if (ret) { 108 printf("Rx: failed to receive: %d\n", ret); 109 return ret; 110 } 111 if (actual_len > rxsize) { 112 debug("Rx: received too many bytes %d\n", actual_len); 113 return -ENOSPC; 114 } 115 ueth->rxlen = actual_len; 116 ueth->rxptr = 0; 117 118 return actual_len ? 0 : -EAGAIN; 119} 120 121void usb_ether_advance_rxbuf(struct ueth_data *ueth, int num_bytes) 122{ 123 ueth->rxptr += num_bytes; 124 if (num_bytes < 0 || ueth->rxptr >= ueth->rxlen) 125 ueth->rxlen = 0; 126} 127 128int usb_ether_get_rx_bytes(struct ueth_data *ueth, uint8_t **ptrp) 129{ 130 if (!ueth->rxlen) 131 return 0; 132 133 *ptrp = &ueth->rxbuf[ueth->rxptr]; 134 135 return ueth->rxlen - ueth->rxptr; 136}