1 /*
2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 #include <string.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <byteswap.h>
30 #include <ipxe/ethernet.h>
31 #include <ipxe/usb.h>
32 #include <ipxe/usbnet.h>
33 #include <ipxe/profile.h>
34 #include "smsc75xx.h"
35
36 /** @file
37 *
38 * SMSC LAN75xx USB Ethernet driver
39 *
40 */
41
42 /** Bulk IN completion profiler */
43 static struct profiler smsc75xx_in_profiler __profiler =
44 { .name = "smsc75xx.in" };
45
46 /** Bulk OUT profiler */
47 static struct profiler smsc75xx_out_profiler __profiler =
48 { .name = "smsc75xx.out" };
49
50 /******************************************************************************
51 *
52 * Statistics (for debugging)
53 *
54 ******************************************************************************
55 */
56
57 /**
58 * Dump statistics (for debugging)
59 *
60 * @v smscusb SMSC USB device
61 * @ret rc Return status code
62 */
smsc75xx_dump_statistics(struct smscusb_device * smscusb)63 int smsc75xx_dump_statistics ( struct smscusb_device *smscusb ) {
64 struct smsc75xx_statistics stats;
65 int rc;
66
67 /* Do nothing unless debugging is enabled */
68 if ( ! DBG_LOG )
69 return 0;
70
71 /* Get statistics */
72 if ( ( rc = smscusb_get_statistics ( smscusb, 0, &stats,
73 sizeof ( stats ) ) ) != 0 ) {
74 DBGC ( smscusb, "SMSC75XX %p could not get statistics: "
75 "%s\n", smscusb, strerror ( rc ) );
76 return rc;
77 }
78
79 /* Dump statistics */
80 DBGC ( smscusb, "SMSC75XX %p RXE fcs %d aln %d frg %d jab %d und %d "
81 "ovr %d drp %d\n", smscusb, le32_to_cpu ( stats.rx.err.fcs ),
82 le32_to_cpu ( stats.rx.err.alignment ),
83 le32_to_cpu ( stats.rx.err.fragment ),
84 le32_to_cpu ( stats.rx.err.jabber ),
85 le32_to_cpu ( stats.rx.err.undersize ),
86 le32_to_cpu ( stats.rx.err.oversize ),
87 le32_to_cpu ( stats.rx.err.dropped ) );
88 DBGC ( smscusb, "SMSC75XX %p RXB ucast %d bcast %d mcast %d\n",
89 smscusb, le32_to_cpu ( stats.rx.byte.unicast ),
90 le32_to_cpu ( stats.rx.byte.broadcast ),
91 le32_to_cpu ( stats.rx.byte.multicast ) );
92 DBGC ( smscusb, "SMSC75XX %p RXF ucast %d bcast %d mcast %d pause "
93 "%d\n", smscusb, le32_to_cpu ( stats.rx.frame.unicast ),
94 le32_to_cpu ( stats.rx.frame.broadcast ),
95 le32_to_cpu ( stats.rx.frame.multicast ),
96 le32_to_cpu ( stats.rx.frame.pause ) );
97 DBGC ( smscusb, "SMSC75XX %p TXE fcs %d def %d car %d cnt %d sgl %d "
98 "mul %d exc %d lat %d\n", smscusb,
99 le32_to_cpu ( stats.tx.err.fcs ),
100 le32_to_cpu ( stats.tx.err.deferral ),
101 le32_to_cpu ( stats.tx.err.carrier ),
102 le32_to_cpu ( stats.tx.err.count ),
103 le32_to_cpu ( stats.tx.err.single ),
104 le32_to_cpu ( stats.tx.err.multiple ),
105 le32_to_cpu ( stats.tx.err.excessive ),
106 le32_to_cpu ( stats.tx.err.late ) );
107 DBGC ( smscusb, "SMSC75XX %p TXB ucast %d bcast %d mcast %d\n",
108 smscusb, le32_to_cpu ( stats.tx.byte.unicast ),
109 le32_to_cpu ( stats.tx.byte.broadcast ),
110 le32_to_cpu ( stats.tx.byte.multicast ) );
111 DBGC ( smscusb, "SMSC75XX %p TXF ucast %d bcast %d mcast %d pause "
112 "%d\n", smscusb, le32_to_cpu ( stats.tx.frame.unicast ),
113 le32_to_cpu ( stats.tx.frame.broadcast ),
114 le32_to_cpu ( stats.tx.frame.multicast ),
115 le32_to_cpu ( stats.tx.frame.pause ) );
116
117 return 0;
118 }
119
120 /******************************************************************************
121 *
122 * Device reset
123 *
124 ******************************************************************************
125 */
126
127 /**
128 * Reset device
129 *
130 * @v smscusb SMSC USB device
131 * @ret rc Return status code
132 */
smsc75xx_reset(struct smscusb_device * smscusb)133 static int smsc75xx_reset ( struct smscusb_device *smscusb ) {
134 uint32_t hw_cfg;
135 unsigned int i;
136 int rc;
137
138 /* Reset device */
139 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_HW_CFG,
140 SMSC75XX_HW_CFG_LRST ) ) != 0 )
141 return rc;
142
143 /* Wait for reset to complete */
144 for ( i = 0 ; i < SMSC75XX_RESET_MAX_WAIT_MS ; i++ ) {
145
146 /* Check if reset has completed */
147 if ( ( rc = smscusb_readl ( smscusb, SMSC75XX_HW_CFG,
148 &hw_cfg ) ) != 0 )
149 return rc;
150 if ( ! ( hw_cfg & SMSC75XX_HW_CFG_LRST ) )
151 return 0;
152
153 /* Delay */
154 mdelay ( 1 );
155 }
156
157 DBGC ( smscusb, "SMSC75XX %p timed out waiting for reset\n",
158 smscusb );
159 return -ETIMEDOUT;
160 }
161
162 /******************************************************************************
163 *
164 * Endpoint operations
165 *
166 ******************************************************************************
167 */
168
169 /**
170 * Complete bulk IN transfer
171 *
172 * @v ep USB endpoint
173 * @v iobuf I/O buffer
174 * @v rc Completion status code
175 */
smsc75xx_in_complete(struct usb_endpoint * ep,struct io_buffer * iobuf,int rc)176 static void smsc75xx_in_complete ( struct usb_endpoint *ep,
177 struct io_buffer *iobuf, int rc ) {
178 struct smscusb_device *smscusb =
179 container_of ( ep, struct smscusb_device, usbnet.in );
180 struct net_device *netdev = smscusb->netdev;
181 struct smsc75xx_rx_header *header;
182
183 /* Profile completions */
184 profile_start ( &smsc75xx_in_profiler );
185
186 /* Ignore packets cancelled when the endpoint closes */
187 if ( ! ep->open ) {
188 free_iob ( iobuf );
189 return;
190 }
191
192 /* Record USB errors against the network device */
193 if ( rc != 0 ) {
194 DBGC ( smscusb, "SMSC75XX %p bulk IN failed: %s\n",
195 smscusb, strerror ( rc ) );
196 goto err;
197 }
198
199 /* Sanity check */
200 if ( iob_len ( iobuf ) < ( sizeof ( *header ) ) ) {
201 DBGC ( smscusb, "SMSC75XX %p underlength bulk IN\n",
202 smscusb );
203 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
204 rc = -EINVAL;
205 goto err;
206 }
207
208 /* Strip header */
209 header = iobuf->data;
210 iob_pull ( iobuf, sizeof ( *header ) );
211
212 /* Check for errors */
213 if ( header->command & cpu_to_le32 ( SMSC75XX_RX_RED ) ) {
214 DBGC ( smscusb, "SMSC75XX %p receive error (%08x):\n",
215 smscusb, le32_to_cpu ( header->command ) );
216 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
217 rc = -EIO;
218 goto err;
219 }
220
221 /* Hand off to network stack */
222 netdev_rx ( netdev, iob_disown ( iobuf ) );
223
224 profile_stop ( &smsc75xx_in_profiler );
225 return;
226
227 err:
228 /* Hand off to network stack */
229 netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
230 }
231
232 /** Bulk IN endpoint operations */
233 struct usb_endpoint_driver_operations smsc75xx_in_operations = {
234 .complete = smsc75xx_in_complete,
235 };
236
237 /**
238 * Transmit packet
239 *
240 * @v smscusb SMSC USB device
241 * @v iobuf I/O buffer
242 * @ret rc Return status code
243 */
smsc75xx_out_transmit(struct smscusb_device * smscusb,struct io_buffer * iobuf)244 static int smsc75xx_out_transmit ( struct smscusb_device *smscusb,
245 struct io_buffer *iobuf ) {
246 struct smsc75xx_tx_header *header;
247 size_t len = iob_len ( iobuf );
248 int rc;
249
250 /* Profile transmissions */
251 profile_start ( &smsc75xx_out_profiler );
252
253 /* Prepend header */
254 if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *header ) ) ) != 0 )
255 return rc;
256 header = iob_push ( iobuf, sizeof ( *header ) );
257 header->command = cpu_to_le32 ( SMSC75XX_TX_FCS | len );
258 header->tag = 0;
259 header->mss = 0;
260
261 /* Enqueue I/O buffer */
262 if ( ( rc = usb_stream ( &smscusb->usbnet.out, iobuf, 0 ) ) != 0 )
263 return rc;
264
265 profile_stop ( &smsc75xx_out_profiler );
266 return 0;
267 }
268
269 /******************************************************************************
270 *
271 * Network device interface
272 *
273 ******************************************************************************
274 */
275
276 /**
277 * Open network device
278 *
279 * @v netdev Network device
280 * @ret rc Return status code
281 */
smsc75xx_open(struct net_device * netdev)282 static int smsc75xx_open ( struct net_device *netdev ) {
283 struct smscusb_device *smscusb = netdev->priv;
284 int rc;
285
286 /* Clear stored interrupt status */
287 smscusb->int_sts = 0;
288
289 /* Configure bulk IN empty response */
290 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_HW_CFG,
291 SMSC75XX_HW_CFG_BIR ) ) != 0 )
292 goto err_hw_cfg;
293
294 /* Open USB network device */
295 if ( ( rc = usbnet_open ( &smscusb->usbnet ) ) != 0 ) {
296 DBGC ( smscusb, "SMSC75XX %p could not open: %s\n",
297 smscusb, strerror ( rc ) );
298 goto err_open;
299 }
300
301 /* Configure interrupt endpoint */
302 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_INT_EP_CTL,
303 ( SMSC75XX_INT_EP_CTL_RDFO_EN |
304 SMSC75XX_INT_EP_CTL_PHY_EN ) ) ) != 0 )
305 goto err_int_ep_ctl;
306
307 /* Configure bulk IN delay */
308 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_BULK_IN_DLY,
309 SMSC75XX_BULK_IN_DLY_SET ( 0 ) ) ) != 0 )
310 goto err_bulk_in_dly;
311
312 /* Configure receive filters */
313 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_RFE_CTL,
314 ( SMSC75XX_RFE_CTL_AB |
315 SMSC75XX_RFE_CTL_AM |
316 SMSC75XX_RFE_CTL_AU ) ) ) != 0 )
317 goto err_rfe_ctl;
318
319 /* Configure receive FIFO */
320 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_FCT_RX_CTL,
321 ( SMSC75XX_FCT_RX_CTL_EN |
322 SMSC75XX_FCT_RX_CTL_BAD ) ) ) != 0 )
323 goto err_fct_rx_ctl;
324
325 /* Configure transmit FIFO */
326 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_FCT_TX_CTL,
327 SMSC75XX_FCT_TX_CTL_EN ) ) != 0 )
328 goto err_fct_tx_ctl;
329
330 /* Configure receive datapath */
331 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_MAC_RX,
332 ( SMSC75XX_MAC_RX_MAX_SIZE_DEFAULT |
333 SMSC75XX_MAC_RX_FCS |
334 SMSC75XX_MAC_RX_EN ) ) ) != 0 )
335 goto err_mac_rx;
336
337 /* Configure transmit datapath */
338 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_MAC_TX,
339 SMSC75XX_MAC_TX_EN ) ) != 0 )
340 goto err_mac_tx;
341
342 /* Set MAC address */
343 if ( ( rc = smscusb_set_address ( smscusb,
344 SMSC75XX_RX_ADDR_BASE ) ) != 0 )
345 goto err_set_address;
346
347 /* Set MAC address perfect filter */
348 if ( ( rc = smscusb_set_filter ( smscusb,
349 SMSC75XX_ADDR_FILT_BASE ) ) != 0 )
350 goto err_set_filter;
351
352 /* Enable PHY interrupts and update link status */
353 if ( ( rc = smscusb_mii_open ( smscusb, SMSC75XX_MII_PHY_INTR_MASK,
354 ( SMSC75XX_PHY_INTR_ANEG_DONE |
355 SMSC75XX_PHY_INTR_LINK_DOWN ) ) ) != 0)
356 goto err_mii_open;
357
358 return 0;
359
360 err_mii_open:
361 err_set_filter:
362 err_set_address:
363 err_mac_tx:
364 err_mac_rx:
365 err_fct_tx_ctl:
366 err_fct_rx_ctl:
367 err_rfe_ctl:
368 err_bulk_in_dly:
369 err_int_ep_ctl:
370 usbnet_close ( &smscusb->usbnet );
371 err_open:
372 err_hw_cfg:
373 smsc75xx_reset ( smscusb );
374 return rc;
375 }
376
377 /**
378 * Close network device
379 *
380 * @v netdev Network device
381 */
smsc75xx_close(struct net_device * netdev)382 static void smsc75xx_close ( struct net_device *netdev ) {
383 struct smscusb_device *smscusb = netdev->priv;
384
385 /* Close USB network device */
386 usbnet_close ( &smscusb->usbnet );
387
388 /* Dump statistics (for debugging) */
389 if ( DBG_LOG )
390 smsc75xx_dump_statistics ( smscusb );
391
392 /* Reset device */
393 smsc75xx_reset ( smscusb );
394 }
395
396 /**
397 * Transmit packet
398 *
399 * @v netdev Network device
400 * @v iobuf I/O buffer
401 * @ret rc Return status code
402 */
smsc75xx_transmit(struct net_device * netdev,struct io_buffer * iobuf)403 int smsc75xx_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
404 struct smscusb_device *smscusb = netdev->priv;
405 int rc;
406
407 /* Transmit packet */
408 if ( ( rc = smsc75xx_out_transmit ( smscusb, iobuf ) ) != 0 )
409 return rc;
410
411 return 0;
412 }
413
414 /**
415 * Poll for completed and received packets
416 *
417 * @v netdev Network device
418 */
smsc75xx_poll(struct net_device * netdev)419 void smsc75xx_poll ( struct net_device *netdev ) {
420 struct smscusb_device *smscusb = netdev->priv;
421 uint32_t int_sts;
422 int rc;
423
424 /* Poll USB bus */
425 usb_poll ( smscusb->bus );
426
427 /* Refill endpoints */
428 if ( ( rc = usbnet_refill ( &smscusb->usbnet ) ) != 0 )
429 netdev_rx_err ( netdev, NULL, rc );
430
431 /* Do nothing more unless there are interrupts to handle */
432 int_sts = smscusb->int_sts;
433 if ( ! int_sts )
434 return;
435
436 /* Check link status if applicable */
437 if ( int_sts & SMSC75XX_INT_STS_PHY_INT ) {
438 smscusb_mii_check_link ( smscusb );
439 int_sts &= ~SMSC75XX_INT_STS_PHY_INT;
440 }
441
442 /* Record RX FIFO overflow if applicable */
443 if ( int_sts & SMSC75XX_INT_STS_RDFO_INT ) {
444 DBGC2 ( smscusb, "SMSC75XX %p RX FIFO overflowed\n", smscusb );
445 netdev_rx_err ( netdev, NULL, -ENOBUFS );
446 int_sts &= ~SMSC75XX_INT_STS_RDFO_INT;
447 }
448
449 /* Check for unexpected interrupts */
450 if ( int_sts ) {
451 DBGC ( smscusb, "SMSC75XX %p unexpected interrupt %#08x\n",
452 smscusb, int_sts );
453 netdev_rx_err ( netdev, NULL, -ENOTTY );
454 }
455
456 /* Clear interrupts */
457 if ( ( rc = smscusb_writel ( smscusb, SMSC75XX_INT_STS,
458 smscusb->int_sts ) ) != 0 )
459 netdev_rx_err ( netdev, NULL, rc );
460 smscusb->int_sts = 0;
461 }
462
463 /** SMSC75xx network device operations */
464 static struct net_device_operations smsc75xx_operations = {
465 .open = smsc75xx_open,
466 .close = smsc75xx_close,
467 .transmit = smsc75xx_transmit,
468 .poll = smsc75xx_poll,
469 };
470
471 /******************************************************************************
472 *
473 * USB interface
474 *
475 ******************************************************************************
476 */
477
478 /**
479 * Probe device
480 *
481 * @v func USB function
482 * @v config Configuration descriptor
483 * @ret rc Return status code
484 */
smsc75xx_probe(struct usb_function * func,struct usb_configuration_descriptor * config)485 static int smsc75xx_probe ( struct usb_function *func,
486 struct usb_configuration_descriptor *config ) {
487 struct net_device *netdev;
488 struct smscusb_device *smscusb;
489 int rc;
490
491 /* Allocate and initialise structure */
492 netdev = alloc_etherdev ( sizeof ( *smscusb ) );
493 if ( ! netdev ) {
494 rc = -ENOMEM;
495 goto err_alloc;
496 }
497 netdev_init ( netdev, &smsc75xx_operations );
498 netdev->dev = &func->dev;
499 smscusb = netdev->priv;
500 memset ( smscusb, 0, sizeof ( *smscusb ) );
501 smscusb_init ( smscusb, netdev, func, &smsc75xx_in_operations );
502 smscusb_mii_init ( smscusb, SMSC75XX_MII_BASE,
503 SMSC75XX_MII_PHY_INTR_SOURCE );
504 usb_refill_init ( &smscusb->usbnet.in, 0, SMSC75XX_IN_MTU,
505 SMSC75XX_IN_MAX_FILL );
506 DBGC ( smscusb, "SMSC75XX %p on %s\n", smscusb, func->name );
507
508 /* Describe USB network device */
509 if ( ( rc = usbnet_describe ( &smscusb->usbnet, config ) ) != 0 ) {
510 DBGC ( smscusb, "SMSC75XX %p could not describe: %s\n",
511 smscusb, strerror ( rc ) );
512 goto err_describe;
513 }
514
515 /* Reset device */
516 if ( ( rc = smsc75xx_reset ( smscusb ) ) != 0 )
517 goto err_reset;
518
519 /* Read MAC address */
520 if ( ( rc = smscusb_eeprom_fetch_mac ( smscusb,
521 SMSC75XX_E2P_BASE ) ) != 0 )
522 goto err_fetch_mac;
523
524 /* Register network device */
525 if ( ( rc = register_netdev ( netdev ) ) != 0 )
526 goto err_register;
527
528 usb_func_set_drvdata ( func, netdev );
529 return 0;
530
531 unregister_netdev ( netdev );
532 err_register:
533 err_fetch_mac:
534 err_reset:
535 err_describe:
536 netdev_nullify ( netdev );
537 netdev_put ( netdev );
538 err_alloc:
539 return rc;
540 }
541
542 /**
543 * Remove device
544 *
545 * @v func USB function
546 */
smsc75xx_remove(struct usb_function * func)547 static void smsc75xx_remove ( struct usb_function *func ) {
548 struct net_device *netdev = usb_func_get_drvdata ( func );
549
550 unregister_netdev ( netdev );
551 netdev_nullify ( netdev );
552 netdev_put ( netdev );
553 }
554
555 /** SMSC75xx device IDs */
556 static struct usb_device_id smsc75xx_ids[] = {
557 {
558 .name = "smsc7500",
559 .vendor = 0x0424,
560 .product = 0x7500,
561 },
562 {
563 .name = "smsc7505",
564 .vendor = 0x0424,
565 .product = 0x7505,
566 },
567 };
568
569 /** SMSC LAN75xx driver */
570 struct usb_driver smsc75xx_driver __usb_driver = {
571 .ids = smsc75xx_ids,
572 .id_count = ( sizeof ( smsc75xx_ids ) / sizeof ( smsc75xx_ids[0] ) ),
573 .class = USB_CLASS_ID ( 0xff, 0x00, 0xff ),
574 .score = USB_SCORE_NORMAL,
575 .probe = smsc75xx_probe,
576 .remove = smsc75xx_remove,
577 };
578