1 /* 2 * Copyright (c) 2011 The Chromium OS Authors. 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 7 #include <common.h> 8 #include <dm.h> 9 #include <usb.h> 10 #include <dm/device-internal.h> 11 12 #include "usb_ether.h" 13 14 typedef void (*usb_eth_before_probe)(void); 15 typedef int (*usb_eth_probe)(struct usb_device *dev, unsigned int ifnum, 16 struct ueth_data *ss); 17 typedef int (*usb_eth_get_info)(struct usb_device *dev, struct ueth_data *ss, 18 struct eth_device *dev_desc); 19 20 struct usb_eth_prob_dev { 21 usb_eth_before_probe before_probe; /* optional */ 22 usb_eth_probe probe; 23 usb_eth_get_info get_info; 24 }; 25 26 /* driver functions go here, each bracketed by #ifdef CONFIG_USB_ETHER_xxx */ 27 static const struct usb_eth_prob_dev prob_dev[] = { 28 #ifdef CONFIG_USB_ETHER_ASIX 29 { 30 .before_probe = asix_eth_before_probe, 31 .probe = asix_eth_probe, 32 .get_info = asix_eth_get_info, 33 }, 34 #endif 35 #ifdef CONFIG_USB_ETHER_ASIX88179 36 { 37 .before_probe = ax88179_eth_before_probe, 38 .probe = ax88179_eth_probe, 39 .get_info = ax88179_eth_get_info, 40 }, 41 #endif 42 #ifdef CONFIG_USB_ETHER_MCS7830 43 { 44 .before_probe = mcs7830_eth_before_probe, 45 .probe = mcs7830_eth_probe, 46 .get_info = mcs7830_eth_get_info, 47 }, 48 #endif 49 #ifdef CONFIG_USB_ETHER_SMSC95XX 50 { 51 .before_probe = smsc95xx_eth_before_probe, 52 .probe = smsc95xx_eth_probe, 53 .get_info = smsc95xx_eth_get_info, 54 }, 55 #endif 56 { }, /* END */ 57 }; 58 59 static int usb_max_eth_dev; /* number of highest available usb eth device */ 60 static struct ueth_data usb_eth[USB_MAX_ETH_DEV]; 61 62 /******************************************************************************* 63 * tell if current ethernet device is a usb dongle 64 */ 65 int is_eth_dev_on_usb_host(void) 66 { 67 int i; 68 struct eth_device *dev = eth_get_dev(); 69 70 if (dev) { 71 for (i = 0; i < usb_max_eth_dev; i++) 72 if (&usb_eth[i].eth_dev == dev) 73 return 1; 74 } 75 return 0; 76 } 77 78 /* 79 * Given a USB device, ask each driver if it can support it, and attach it 80 * to the first driver that says 'yes' 81 */ 82 static void probe_valid_drivers(struct usb_device *dev) 83 { 84 struct eth_device *eth; 85 int j; 86 87 for (j = 0; prob_dev[j].probe && prob_dev[j].get_info; j++) { 88 if (!prob_dev[j].probe(dev, 0, &usb_eth[usb_max_eth_dev])) 89 continue; 90 /* 91 * ok, it is a supported eth device. Get info and fill it in 92 */ 93 eth = &usb_eth[usb_max_eth_dev].eth_dev; 94 if (prob_dev[j].get_info(dev, 95 &usb_eth[usb_max_eth_dev], 96 eth)) { 97 /* found proper driver */ 98 /* register with networking stack */ 99 usb_max_eth_dev++; 100 101 /* 102 * usb_max_eth_dev must be incremented prior to this 103 * call since eth_current_changed (internally called) 104 * relies on it 105 */ 106 eth_register(eth); 107 if (eth_write_hwaddr(eth, "usbeth", 108 usb_max_eth_dev - 1)) 109 puts("Warning: failed to set MAC address\n"); 110 break; 111 } 112 } 113 } 114 115 /******************************************************************************* 116 * scan the usb and reports device info 117 * to the user if mode = 1 118 * returns current device or -1 if no 119 */ 120 int usb_host_eth_scan(int mode) 121 { 122 int i, old_async; 123 124 if (mode == 1) 125 printf(" scanning usb for ethernet devices... "); 126 127 old_async = usb_disable_asynch(1); /* asynch transfer not allowed */ 128 129 /* unregister a previously detected device */ 130 for (i = 0; i < usb_max_eth_dev; i++) 131 eth_unregister(&usb_eth[i].eth_dev); 132 133 memset(usb_eth, 0, sizeof(usb_eth)); 134 135 for (i = 0; prob_dev[i].probe; i++) { 136 if (prob_dev[i].before_probe) 137 prob_dev[i].before_probe(); 138 } 139 140 usb_max_eth_dev = 0; 141 #ifdef CONFIG_DM_USB 142 /* 143 * TODO: We should add USB_DEVICE() declarations to each USB ethernet 144 * driver and then most of this file can be removed. 145 */ 146 struct udevice *bus; 147 struct uclass *uc; 148 int ret; 149 150 ret = uclass_get(UCLASS_USB, &uc); 151 if (ret) 152 return ret; 153 uclass_foreach_dev(bus, uc) { 154 for (i = 0; i < USB_MAX_DEVICE; i++) { 155 struct usb_device *dev; 156 157 dev = usb_get_dev_index(bus, i); /* get device */ 158 debug("i=%d, %s\n", i, dev ? dev->dev->name : "(done)"); 159 if (!dev) 160 break; /* no more devices available */ 161 162 /* 163 * find valid usb_ether driver for this device, 164 * if any 165 */ 166 probe_valid_drivers(dev); 167 168 /* check limit */ 169 if (usb_max_eth_dev == USB_MAX_ETH_DEV) 170 break; 171 } /* for */ 172 } 173 #else 174 for (i = 0; i < USB_MAX_DEVICE; i++) { 175 struct usb_device *dev; 176 177 dev = usb_get_dev_index(i); /* get device */ 178 debug("i=%d\n", i); 179 if (!dev) 180 break; /* no more devices available */ 181 182 /* find valid usb_ether driver for this device, if any */ 183 probe_valid_drivers(dev); 184 185 /* check limit */ 186 if (usb_max_eth_dev == USB_MAX_ETH_DEV) 187 break; 188 } /* for */ 189 #endif 190 if (usb_max_eth_dev == USB_MAX_ETH_DEV) { 191 printf("max USB Ethernet Device reached: %d stopping\n", 192 usb_max_eth_dev); 193 } 194 usb_disable_asynch(old_async); /* restore asynch value */ 195 printf("%d Ethernet Device(s) found\n", usb_max_eth_dev); 196 if (usb_max_eth_dev > 0) 197 return 0; 198 return -1; 199 } 200