iPXE
smscusb.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2017 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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <string.h>
28#include <errno.h>
29#include <unistd.h>
30#include <ipxe/usb.h>
31#include <ipxe/usbnet.h>
32#include <ipxe/ethernet.h>
33#include <ipxe/profile.h>
34#include <ipxe/fdt.h>
35#include "smscusb.h"
36
37/** @file
38 *
39 * SMSC USB Ethernet drivers
40 *
41 */
42
43/** Interrupt completion profiler */
44static struct profiler smscusb_intr_profiler __profiler =
45 { .name = "smscusb.intr" };
46
47/******************************************************************************
48 *
49 * Register access
50 *
51 ******************************************************************************
52 */
53
54/**
55 * Write register (without byte-swapping)
56 *
57 * @v smscusb Smscusb device
58 * @v address Register address
59 * @v value Register value
60 * @ret rc Return status code
61 */
62int smscusb_raw_writel ( struct smscusb_device *smscusb, unsigned int address,
63 uint32_t value ) {
64 int rc;
65
66 /* Write register */
67 DBGCIO ( smscusb, "SMSCUSB %p [%03x] <= %08x\n",
68 smscusb, address, le32_to_cpu ( value ) );
69 if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_REGISTER_WRITE, 0,
70 address, &value, sizeof ( value ) ) ) != 0 ) {
71 DBGC ( smscusb, "SMSCUSB %p could not write %03x: %s\n",
72 smscusb, address, strerror ( rc ) );
73 return rc;
74 }
75
76 return 0;
77}
78
79/**
80 * Read register (without byte-swapping)
81 *
82 * @v smscusb SMSC USB device
83 * @v address Register address
84 * @ret value Register value
85 * @ret rc Return status code
86 */
87int smscusb_raw_readl ( struct smscusb_device *smscusb, unsigned int address,
88 uint32_t *value ) {
89 int rc;
90
91 /* Read register */
92 if ( ( rc = usb_control ( smscusb->usb, SMSCUSB_REGISTER_READ, 0,
93 address, value, sizeof ( *value ) ) ) != 0 ) {
94 DBGC ( smscusb, "SMSCUSB %p could not read %03x: %s\n",
95 smscusb, address, strerror ( rc ) );
96 return rc;
97 }
98 DBGCIO ( smscusb, "SMSCUSB %p [%03x] => %08x\n",
99 smscusb, address, le32_to_cpu ( *value ) );
100
101 return 0;
102}
103
104/******************************************************************************
105 *
106 * EEPROM access
107 *
108 ******************************************************************************
109 */
110
111/**
112 * Wait for EEPROM to become idle
113 *
114 * @v smscusb SMSC USB device
115 * @v e2p_base E2P register base
116 * @ret rc Return status code
117 */
118static int smscusb_eeprom_wait ( struct smscusb_device *smscusb,
119 unsigned int e2p_base ) {
120 uint32_t e2p_cmd;
121 unsigned int i;
122 int rc;
123
124 /* Wait for EPC_BSY to become clear */
125 for ( i = 0 ; i < SMSCUSB_EEPROM_MAX_WAIT_MS ; i++ ) {
126
127 /* Read E2P_CMD and check EPC_BSY */
128 if ( ( rc = smscusb_readl ( smscusb,
129 ( e2p_base + SMSCUSB_E2P_CMD ),
130 &e2p_cmd ) ) != 0 )
131 return rc;
132 if ( ! ( e2p_cmd & SMSCUSB_E2P_CMD_EPC_BSY ) )
133 return 0;
134
135 /* Delay */
136 mdelay ( 1 );
137 }
138
139 DBGC ( smscusb, "SMSCUSB %p timed out waiting for EEPROM\n",
140 smscusb );
141 return -ETIMEDOUT;
142}
143
144/**
145 * Read byte from EEPROM
146 *
147 * @v smscusb SMSC USB device
148 * @v e2p_base E2P register base
149 * @v address EEPROM address
150 * @ret byte Byte read, or negative error
151 */
152static int smscusb_eeprom_read_byte ( struct smscusb_device *smscusb,
153 unsigned int e2p_base,
154 unsigned int address ) {
155 uint32_t e2p_cmd;
156 uint32_t e2p_data;
157 int rc;
158
159 /* Wait for EEPROM to become idle */
160 if ( ( rc = smscusb_eeprom_wait ( smscusb, e2p_base ) ) != 0 )
161 return rc;
162
163 /* Initiate read command */
166 if ( ( rc = smscusb_writel ( smscusb, ( e2p_base + SMSCUSB_E2P_CMD ),
167 e2p_cmd ) ) != 0 )
168 return rc;
169
170 /* Wait for command to complete */
171 if ( ( rc = smscusb_eeprom_wait ( smscusb, e2p_base ) ) != 0 )
172 return rc;
173
174 /* Read EEPROM data */
175 if ( ( rc = smscusb_readl ( smscusb, ( e2p_base + SMSCUSB_E2P_DATA ),
176 &e2p_data ) ) != 0 )
177 return rc;
178
179 return SMSCUSB_E2P_DATA_GET ( e2p_data );
180}
181
182/**
183 * Read data from EEPROM
184 *
185 * @v smscusb SMSC USB device
186 * @v e2p_base E2P register base
187 * @v address EEPROM address
188 * @v data Data buffer
189 * @v len Length of data
190 * @ret rc Return status code
191 */
192static int smscusb_eeprom_read ( struct smscusb_device *smscusb,
193 unsigned int e2p_base, unsigned int address,
194 void *data, size_t len ) {
195 uint8_t *bytes;
196 int byte;
197
198 /* Read bytes */
199 for ( bytes = data ; len-- ; address++, bytes++ ) {
200 byte = smscusb_eeprom_read_byte ( smscusb, e2p_base, address );
201 if ( byte < 0 )
202 return byte;
203 *bytes = byte;
204 }
205
206 return 0;
207}
208
209/**
210 * Fetch MAC address from EEPROM
211 *
212 * @v smscusb SMSC USB device
213 * @v e2p_base E2P register base
214 * @ret rc Return status code
215 */
217 unsigned int e2p_base ) {
218 struct net_device *netdev = smscusb->netdev;
219 int rc;
220
221 /* Read MAC address from EEPROM */
222 if ( ( rc = smscusb_eeprom_read ( smscusb, e2p_base, SMSCUSB_EEPROM_MAC,
223 netdev->hw_addr, ETH_ALEN ) ) != 0 )
224 return rc;
225
226 /* Check that EEPROM is physically present */
227 if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
228 DBGC ( smscusb, "SMSCUSB %p has no EEPROM MAC (%s)\n",
229 smscusb, eth_ntoa ( netdev->hw_addr ) );
230 return -ENODEV;
231 }
232
233 DBGC ( smscusb, "SMSCUSB %p using EEPROM MAC %s\n",
234 smscusb, eth_ntoa ( netdev->hw_addr ) );
235 return 0;
236}
237
238/******************************************************************************
239 *
240 * OTP access
241 *
242 ******************************************************************************
243 */
244
245/**
246 * Power up OTP
247 *
248 * @v smscusb SMSC USB device
249 * @v otp_base OTP register base
250 * @ret rc Return status code
251 */
252static int smscusb_otp_power_up ( struct smscusb_device *smscusb,
253 unsigned int otp_base ) {
254 uint32_t otp_power;
255 unsigned int i;
256 int rc;
257
258 /* Power up OTP */
259 if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_POWER ),
260 0 ) ) != 0 )
261 return rc;
262
263 /* Wait for OTP_POWER_DOWN to become clear */
264 for ( i = 0 ; i < SMSCUSB_OTP_MAX_WAIT_MS ; i++ ) {
265
266 /* Read OTP_POWER and check OTP_POWER_DOWN */
267 if ( ( rc = smscusb_readl ( smscusb,
268 ( otp_base + SMSCUSB_OTP_POWER ),
269 &otp_power ) ) != 0 )
270 return rc;
271 if ( ! ( otp_power & SMSCUSB_OTP_POWER_DOWN ) )
272 return 0;
273
274 /* Delay */
275 mdelay ( 1 );
276 }
277
278 DBGC ( smscusb, "SMSCUSB %p timed out waiting for OTP power up\n",
279 smscusb );
280 return -ETIMEDOUT;
281}
282
283/**
284 * Wait for OTP to become idle
285 *
286 * @v smscusb SMSC USB device
287 * @v otp_base OTP register base
288 * @ret rc Return status code
289 */
290static int smscusb_otp_wait ( struct smscusb_device *smscusb,
291 unsigned int otp_base ) {
292 uint32_t otp_status;
293 unsigned int i;
294 int rc;
295
296 /* Wait for OTP_STATUS_BUSY to become clear */
297 for ( i = 0 ; i < SMSCUSB_OTP_MAX_WAIT_MS ; i++ ) {
298
299 /* Read OTP_STATUS and check OTP_STATUS_BUSY */
300 if ( ( rc = smscusb_readl ( smscusb,
301 ( otp_base + SMSCUSB_OTP_STATUS ),
302 &otp_status ) ) != 0 )
303 return rc;
304 if ( ! ( otp_status & SMSCUSB_OTP_STATUS_BUSY ) )
305 return 0;
306
307 /* Delay */
308 mdelay ( 1 );
309 }
310
311 DBGC ( smscusb, "SMSCUSB %p timed out waiting for OTP\n",
312 smscusb );
313 return -ETIMEDOUT;
314}
315
316/**
317 * Read byte from OTP
318 *
319 * @v smscusb SMSC USB device
320 * @v otp_base OTP register base
321 * @v address OTP address
322 * @ret byte Byte read, or negative error
323 */
324static int smscusb_otp_read_byte ( struct smscusb_device *smscusb,
325 unsigned int otp_base,
326 unsigned int address ) {
327 uint8_t addrh = ( address >> 8 );
328 uint8_t addrl = ( address >> 0 );
329 uint32_t otp_data;
330 int rc;
331
332 /* Wait for OTP to become idle */
333 if ( ( rc = smscusb_otp_wait ( smscusb, otp_base ) ) != 0 )
334 return rc;
335
336 /* Initiate read command */
337 if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_ADDRH ),
338 addrh ) ) != 0 )
339 return rc;
340 if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_ADDRL ),
341 addrl ) ) != 0 )
342 return rc;
343 if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_CMD ),
344 SMSCUSB_OTP_CMD_READ ) ) != 0 )
345 return rc;
346 if ( ( rc = smscusb_writel ( smscusb, ( otp_base + SMSCUSB_OTP_GO ),
347 SMSCUSB_OTP_GO_GO ) ) != 0 )
348 return rc;
349
350 /* Wait for command to complete */
351 if ( ( rc = smscusb_otp_wait ( smscusb, otp_base ) ) != 0 )
352 return rc;
353
354 /* Read OTP data */
355 if ( ( rc = smscusb_readl ( smscusb, ( otp_base + SMSCUSB_OTP_DATA ),
356 &otp_data ) ) != 0 )
357 return rc;
358
359 return SMSCUSB_OTP_DATA_GET ( otp_data );
360}
361
362/**
363 * Read data from OTP
364 *
365 * @v smscusb SMSC USB device
366 * @v otp_base OTP register base
367 * @v address OTP address
368 * @v data Data buffer
369 * @v len Length of data
370 * @ret rc Return status code
371 */
372static int smscusb_otp_read ( struct smscusb_device *smscusb,
373 unsigned int otp_base, unsigned int address,
374 void *data, size_t len ) {
375 uint8_t *bytes;
376 int byte;
377 int rc;
378
379 /* Power up OTP */
380 if ( ( rc = smscusb_otp_power_up ( smscusb, otp_base ) ) != 0 )
381 return rc;
382
383 /* Read bytes */
384 for ( bytes = data ; len-- ; address++, bytes++ ) {
385 byte = smscusb_otp_read_byte ( smscusb, otp_base, address );
386 if ( byte < 0 )
387 return byte;
388 *bytes = byte;
389 }
390
391 return 0;
392}
393
394/**
395 * Fetch MAC address from OTP
396 *
397 * @v smscusb SMSC USB device
398 * @v otp_base OTP register base
399 * @ret rc Return status code
400 */
402 unsigned int otp_base ) {
403 struct net_device *netdev = smscusb->netdev;
405 unsigned int address;
406 int rc;
407
408 /* Read OTP signature byte */
409 if ( ( rc = smscusb_otp_read ( smscusb, otp_base, 0, &signature,
410 sizeof ( signature ) ) ) != 0 )
411 return rc;
412
413 /* Determine location of MAC address */
414 switch ( signature ) {
417 break;
420 break;
421 default:
422 DBGC ( smscusb, "SMSCUSB %p unknown OTP signature %#02x\n",
423 smscusb, signature );
424 return -ENOTSUP;
425 }
426
427 /* Read MAC address from OTP */
428 if ( ( rc = smscusb_otp_read ( smscusb, otp_base, address,
429 netdev->hw_addr, ETH_ALEN ) ) != 0 )
430 return rc;
431
432 /* Check that OTP is valid */
433 if ( ! is_valid_ether_addr ( netdev->hw_addr ) ) {
434 DBGC ( smscusb, "SMSCUSB %p has no layout %#02x OTP MAC (%s)\n",
435 smscusb, signature, eth_ntoa ( netdev->hw_addr ) );
436 return -ENODEV;
437 }
438
439 DBGC ( smscusb, "SMSCUSB %p using layout %#02x OTP MAC %s\n",
440 smscusb, signature, eth_ntoa ( netdev->hw_addr ) );
441 return 0;
442}
443
444/******************************************************************************
445 *
446 * Device tree
447 *
448 ******************************************************************************
449 */
450
451/**
452 * Fetch MAC address from device tree
453 *
454 * @v smscusb SMSC USB device
455 * @ret rc Return status code
456 */
457int smscusb_fdt_fetch_mac ( struct smscusb_device *smscusb ) {
458 struct net_device *netdev = smscusb->netdev;
459 unsigned int offset;
460 int rc;
461
462 /* Look for "ethernet[0]" alias */
463 if ( ( rc = fdt_alias ( &sysfdt, "ethernet", &offset ) != 0 ) &&
464 ( rc = fdt_alias ( &sysfdt, "ethernet0", &offset ) != 0 ) ) {
465 return rc;
466 }
467
468 /* Fetch MAC address */
469 if ( ( rc = fdt_mac ( &sysfdt, offset, netdev ) ) != 0 )
470 return rc;
471
472 DBGC ( smscusb, "SMSCUSB %p using FDT MAC %s\n",
473 smscusb, eth_ntoa ( netdev->hw_addr ) );
474 return 0;
475}
476
477/******************************************************************************
478 *
479 * MII access
480 *
481 ******************************************************************************
482 */
483
484/**
485 * Wait for MII to become idle
486 *
487 * @v smscusb SMSC USB device
488 * @ret rc Return status code
489 */
490static int smscusb_mii_wait ( struct smscusb_device *smscusb ) {
491 unsigned int base = smscusb->mii_base;
492 uint32_t mii_access;
493 unsigned int i;
494 int rc;
495
496 /* Wait for MIIBZY to become clear */
497 for ( i = 0 ; i < SMSCUSB_MII_MAX_WAIT_MS ; i++ ) {
498
499 /* Read MII_ACCESS and check MIIBZY */
500 if ( ( rc = smscusb_readl ( smscusb,
502 &mii_access ) ) != 0 )
503 return rc;
504 if ( ! ( mii_access & SMSCUSB_MII_ACCESS_MIIBZY ) )
505 return 0;
506
507 /* Delay */
508 mdelay ( 1 );
509 }
510
511 DBGC ( smscusb, "SMSCUSB %p timed out waiting for MII\n",
512 smscusb );
513 return -ETIMEDOUT;
514}
515
516/**
517 * Read from MII register
518 *
519 * @v mdio MII interface
520 * @v phy PHY address
521 * @v reg Register address
522 * @ret value Data read, or negative error
523 */
524static int smscusb_mii_read ( struct mii_interface *mdio,
525 unsigned int phy __unused, unsigned int reg ) {
526 struct smscusb_device *smscusb =
528 unsigned int base = smscusb->mii_base;
529 uint32_t mii_access;
530 uint32_t mii_data;
531 int rc;
532
533 /* Wait for MII to become idle */
534 if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
535 return rc;
536
537 /* Initiate read command */
538 mii_access = ( SMSCUSB_MII_ACCESS_PHY_ADDRESS |
541 if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_ACCESS ),
542 mii_access ) ) != 0 )
543 return rc;
544
545 /* Wait for command to complete */
546 if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
547 return rc;
548
549 /* Read MII data */
550 if ( ( rc = smscusb_readl ( smscusb, ( base + SMSCUSB_MII_DATA ),
551 &mii_data ) ) != 0 )
552 return rc;
553
554 return SMSCUSB_MII_DATA_GET ( mii_data );
555}
556
557/**
558 * Write to MII register
559 *
560 * @v mdio MII interface
561 * @v phy PHY address
562 * @v reg Register address
563 * @v data Data to write
564 * @ret rc Return status code
565 */
567 unsigned int phy __unused, unsigned int reg,
568 unsigned int data ) {
569 struct smscusb_device *smscusb =
571 unsigned int base = smscusb->mii_base;
572 uint32_t mii_access;
573 uint32_t mii_data;
574 int rc;
575
576 /* Wait for MII to become idle */
577 if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
578 return rc;
579
580 /* Write MII data */
581 mii_data = SMSCUSB_MII_DATA_SET ( data );
582 if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_DATA ),
583 mii_data ) ) != 0 )
584 return rc;
585
586 /* Initiate write command */
587 mii_access = ( SMSCUSB_MII_ACCESS_PHY_ADDRESS |
591 if ( ( rc = smscusb_writel ( smscusb, ( base + SMSCUSB_MII_ACCESS ),
592 mii_access ) ) != 0 )
593 return rc;
594
595 /* Wait for command to complete */
596 if ( ( rc = smscusb_mii_wait ( smscusb ) ) != 0 )
597 return rc;
598
599 return 0;
600}
601
602/** MII operations */
607
608/**
609 * Check link status
610 *
611 * @v smscusb SMSC USB device
612 * @ret rc Return status code
613 */
614int smscusb_mii_check_link ( struct smscusb_device *smscusb ) {
615 struct net_device *netdev = smscusb->netdev;
616 int intr;
617 int rc;
618
619 /* Read PHY interrupt source */
620 intr = mii_read ( &smscusb->mii, smscusb->phy_source );
621 if ( intr < 0 ) {
622 rc = intr;
623 DBGC ( smscusb, "SMSCUSB %p could not get PHY interrupt "
624 "source: %s\n", smscusb, strerror ( rc ) );
625 return rc;
626 }
627
628 /* Acknowledge PHY interrupt */
629 if ( ( rc = mii_write ( &smscusb->mii, smscusb->phy_source,
630 intr ) ) != 0 ) {
631 DBGC ( smscusb, "SMSCUSB %p could not acknowledge PHY "
632 "interrupt: %s\n", smscusb, strerror ( rc ) );
633 return rc;
634 }
635
636 /* Check link status */
637 if ( ( rc = mii_check_link ( &smscusb->mii, netdev ) ) != 0 ) {
638 DBGC ( smscusb, "SMSCUSB %p could not check link: %s\n",
639 smscusb, strerror ( rc ) );
640 return rc;
641 }
642
643 DBGC ( smscusb, "SMSCUSB %p link %s (intr %#04x)\n",
644 smscusb, ( netdev_link_ok ( netdev ) ? "up" : "down" ), intr );
645 return 0;
646}
647
648/**
649 * Enable PHY interrupts and update link status
650 *
651 * @v smscusb SMSC USB device
652 * @v phy_mask PHY interrupt mask register
653 * @v intrs PHY interrupts to enable
654 * @ret rc Return status code
655 */
656int smscusb_mii_open ( struct smscusb_device *smscusb,
657 unsigned int phy_mask, unsigned int intrs ) {
658 int rc;
659
660 /* Enable PHY interrupts */
661 if ( ( rc = mii_write ( &smscusb->mii, phy_mask, intrs ) ) != 0 ) {
662 DBGC ( smscusb, "SMSCUSB %p could not set PHY interrupt "
663 "mask: %s\n", smscusb, strerror ( rc ) );
664 return rc;
665 }
666
667 /* Update link status */
668 smscusb_mii_check_link ( smscusb );
669
670 return 0;
671}
672
673/******************************************************************************
674 *
675 * Receive filtering
676 *
677 ******************************************************************************
678 */
679
680/**
681 * Set receive address
682 *
683 * @v smscusb SMSC USB device
684 * @v addr_base Receive address register base
685 * @ret rc Return status code
686 */
688 unsigned int addr_base ) {
689 struct net_device *netdev = smscusb->netdev;
690 union smscusb_mac mac;
691 int rc;
692
693 /* Copy MAC address */
694 memset ( &mac, 0, sizeof ( mac ) );
695 memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
696
697 /* Write MAC address high register */
698 if ( ( rc = smscusb_raw_writel ( smscusb,
699 ( addr_base + SMSCUSB_RX_ADDRH ),
700 mac.addr.h ) ) != 0 )
701 return rc;
702
703 /* Write MAC address low register */
704 if ( ( rc = smscusb_raw_writel ( smscusb,
705 ( addr_base + SMSCUSB_RX_ADDRL ),
706 mac.addr.l ) ) != 0 )
707 return rc;
708
709 return 0;
710}
711
712/**
713 * Set receive filter
714 *
715 * @v smscusb SMSC USB device
716 * @v filt_base Receive filter register base
717 * @ret rc Return status code
718 */
719int smscusb_set_filter ( struct smscusb_device *smscusb,
720 unsigned int filt_base ) {
721 struct net_device *netdev = smscusb->netdev;
722 union smscusb_mac mac;
723 int rc;
724
725 /* Copy MAC address */
726 memset ( &mac, 0, sizeof ( mac ) );
727 memcpy ( mac.raw, netdev->ll_addr, ETH_ALEN );
729
730 /* Write MAC address perfect filter high register */
731 if ( ( rc = smscusb_raw_writel ( smscusb,
732 ( filt_base + SMSCUSB_ADDR_FILTH(0) ),
733 mac.addr.h ) ) != 0 )
734 return rc;
735
736 /* Write MAC address perfect filter low register */
737 if ( ( rc = smscusb_raw_writel ( smscusb,
738 ( filt_base + SMSCUSB_ADDR_FILTL(0) ),
739 mac.addr.l ) ) != 0 )
740 return rc;
741
742 return 0;
743}
744
745/******************************************************************************
746 *
747 * Endpoint operations
748 *
749 ******************************************************************************
750 */
751
752/**
753 * Complete interrupt transfer
754 *
755 * @v ep USB endpoint
756 * @v iobuf I/O buffer
757 * @v rc Completion status code
758 */
759static void smscusb_intr_complete ( struct usb_endpoint *ep,
760 struct io_buffer *iobuf, int rc ) {
761 struct smscusb_device *smscusb =
762 container_of ( ep, struct smscusb_device, usbnet.intr );
763 struct net_device *netdev = smscusb->netdev;
764 struct smscusb_interrupt *intr;
765
766 /* Profile completions */
767 profile_start ( &smscusb_intr_profiler );
768
769 /* Ignore packets cancelled when the endpoint closes */
770 if ( ! ep->open )
771 goto done;
772
773 /* Record USB errors against the network device */
774 if ( rc != 0 ) {
775 DBGC ( smscusb, "SMSCUSB %p interrupt failed: %s\n",
776 smscusb, strerror ( rc ) );
777 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
779 goto done;
780 }
781
782 /* Extract interrupt data */
783 if ( iob_len ( iobuf ) != sizeof ( *intr ) ) {
784 DBGC ( smscusb, "SMSCUSB %p malformed interrupt\n",
785 smscusb );
786 DBGC_HDA ( smscusb, 0, iobuf->data, iob_len ( iobuf ) );
788 goto done;
789 }
790 intr = iobuf->data;
791
792 /* Record interrupt status */
793 smscusb->int_sts = le32_to_cpu ( intr->int_sts );
794 profile_stop ( &smscusb_intr_profiler );
795
796 done:
797 /* Free I/O buffer */
798 free_iob ( iobuf );
799}
800
801/** Interrupt endpoint operations */
805
806/**
807 * Complete bulk OUT transfer
808 *
809 * @v ep USB endpoint
810 * @v iobuf I/O buffer
811 * @v rc Completion status code
812 */
813static void smscusb_out_complete ( struct usb_endpoint *ep,
814 struct io_buffer *iobuf, int rc ) {
815 struct smscusb_device *smscusb =
816 container_of ( ep, struct smscusb_device, usbnet.out );
817 struct net_device *netdev = smscusb->netdev;
818
819 /* Report TX completion */
820 netdev_tx_complete_err ( netdev, iobuf, rc );
821}
822
823/** Bulk OUT endpoint operations */
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
u8 signature
CPU signature.
Definition CIB_PRM.h:7
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
pseudo_bit_t value[0x00020]
Definition arbel.h:2
unsigned int uint32_t
Definition stdint.h:12
unsigned char uint8_t
Definition stdint.h:10
struct bofm_section_header done
Definition bofm_test.c:46
uint16_t offset
Offset to command line.
Definition bzimage.h:3
uint32_t addrl
Definition dwmac.h:0
ring len
Length.
Definition dwmac.h:226
uint32_t addrh
Definition dwmac.h:1
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint64_t address
Base address.
Definition ena.h:13
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
uint8_t intr
Interrupts enabled.
Definition ena.h:3
static int mii_read(int phy_id, int location)
Definition epic100.c:500
Error codes.
const char * eth_ntoa(const void *ll_addr)
Transcribe Ethernet address.
Definition ethernet.c:176
Ethernet protocol.
static int is_valid_ether_addr(const void *addr)
Check if Ethernet address is valid.
Definition ethernet.h:78
int fdt_mac(struct fdt *fdt, unsigned int offset, struct net_device *netdev)
Get MAC address from property.
Definition fdt.c:867
int fdt_alias(struct fdt *fdt, const char *name, unsigned int *offset)
Find node by alias.
Definition fdt.c:466
struct fdt sysfdt
The system flattened device tree (if present)
Definition fdt.c:45
static struct net_device * netdev
Definition gdbudp.c:53
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define DBGCIO(...)
Definition compiler.h:556
#define DBGC_HDA(...)
Definition compiler.h:506
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define ENODEV
No such device.
Definition errno.h:510
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
uint8_t bytes[64]
Definition ib_mad.h:5
#define ETH_ALEN
Definition if_ether.h:9
#define le32_to_cpu(value)
Definition byteswap.h:114
#define cpu_to_le32(value)
Definition byteswap.h:108
Flattened Device Tree.
Profiling.
#define __profiler
Declare a profiler.
Definition profile.h:61
static void profile_stop(struct profiler *profiler)
Stop profiling.
Definition profile.h:174
static void profile_start(struct profiler *profiler)
Start profiling.
Definition profile.h:161
Universal Serial Bus (USB)
String functions.
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memset(void *dest, int character, size_t len) __nonnull
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
static int mii_write(struct mii_device *mii, unsigned int reg, unsigned int data)
Write to MII register.
Definition mii.h:105
uint32_t base
Base.
Definition librm.h:3
int mii_check_link(struct mii_device *mii, struct net_device *netdev)
Update link status via MII.
Definition mii.c:127
static unsigned int unsigned int reg
Definition myson.h:162
void netdev_tx_complete_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Complete network transmission.
Definition netdevice.c:471
void netdev_rx_err(struct net_device *netdev, struct io_buffer *iobuf, int rc)
Discard received packet.
Definition netdevice.c:587
static int netdev_link_ok(struct net_device *netdev)
Check link state of network device.
Definition netdevice.h:640
unsigned char byte
Definition smc9000.h:38
static int smscusb_eeprom_read(struct smscusb_device *smscusb, unsigned int e2p_base, unsigned int address, void *data, size_t len)
Read data from EEPROM.
Definition smscusb.c:192
int smscusb_eeprom_fetch_mac(struct smscusb_device *smscusb, unsigned int e2p_base)
Fetch MAC address from EEPROM.
Definition smscusb.c:216
static void smscusb_out_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete bulk OUT transfer.
Definition smscusb.c:813
struct usb_endpoint_driver_operations smscusb_out_operations
Bulk OUT endpoint operations.
Definition smscusb.c:824
static int smscusb_mii_wait(struct smscusb_device *smscusb)
Wait for MII to become idle.
Definition smscusb.c:490
int smscusb_otp_fetch_mac(struct smscusb_device *smscusb, unsigned int otp_base)
Fetch MAC address from OTP.
Definition smscusb.c:401
static int smscusb_mii_read(struct mii_interface *mdio, unsigned int phy __unused, unsigned int reg)
Read from MII register.
Definition smscusb.c:524
static int smscusb_eeprom_read_byte(struct smscusb_device *smscusb, unsigned int e2p_base, unsigned int address)
Read byte from EEPROM.
Definition smscusb.c:152
struct usb_endpoint_driver_operations smscusb_intr_operations
Interrupt endpoint operations.
Definition smscusb.c:802
int smscusb_fdt_fetch_mac(struct smscusb_device *smscusb)
Fetch MAC address from device tree.
Definition smscusb.c:457
static int smscusb_otp_read_byte(struct smscusb_device *smscusb, unsigned int otp_base, unsigned int address)
Read byte from OTP.
Definition smscusb.c:324
int smscusb_set_address(struct smscusb_device *smscusb, unsigned int addr_base)
Set receive address.
Definition smscusb.c:687
static int smscusb_mii_write(struct mii_interface *mdio, unsigned int phy __unused, unsigned int reg, unsigned int data)
Write to MII register.
Definition smscusb.c:566
int smscusb_set_filter(struct smscusb_device *smscusb, unsigned int filt_base)
Set receive filter.
Definition smscusb.c:719
int smscusb_raw_readl(struct smscusb_device *smscusb, unsigned int address, uint32_t *value)
Read register (without byte-swapping)
Definition smscusb.c:87
struct mii_operations smscusb_mii_operations
MII operations.
Definition smscusb.c:603
static void smscusb_intr_complete(struct usb_endpoint *ep, struct io_buffer *iobuf, int rc)
Complete interrupt transfer.
Definition smscusb.c:759
static int smscusb_otp_power_up(struct smscusb_device *smscusb, unsigned int otp_base)
Power up OTP.
Definition smscusb.c:252
int smscusb_mii_open(struct smscusb_device *smscusb, unsigned int phy_mask, unsigned int intrs)
Enable PHY interrupts and update link status.
Definition smscusb.c:656
static int smscusb_eeprom_wait(struct smscusb_device *smscusb, unsigned int e2p_base)
Wait for EEPROM to become idle.
Definition smscusb.c:118
int smscusb_raw_writel(struct smscusb_device *smscusb, unsigned int address, uint32_t value)
Write register (without byte-swapping)
Definition smscusb.c:62
int smscusb_mii_check_link(struct smscusb_device *smscusb)
Check link status.
Definition smscusb.c:614
static int smscusb_otp_read(struct smscusb_device *smscusb, unsigned int otp_base, unsigned int address, void *data, size_t len)
Read data from OTP.
Definition smscusb.c:372
static int smscusb_otp_wait(struct smscusb_device *smscusb, unsigned int otp_base)
Wait for OTP to become idle.
Definition smscusb.c:290
SMSC USB Ethernet drivers.
#define SMSCUSB_OTP_GO
OTP command initiation register offset.
Definition smscusb.h:74
#define SMSCUSB_MII_MAX_WAIT_MS
Maximum time to wait for MII (in milliseconds)
Definition smscusb.h:110
#define SMSCUSB_MII_DATA
MII data register offset.
Definition smscusb.h:104
#define SMSCUSB_MII_ACCESS_PHY_ADDRESS
PHY address.
Definition smscusb.h:98
#define SMSCUSB_OTP_2_MAC
OTP layout 2 MAC address offset.
Definition smscusb.h:94
#define SMSCUSB_OTP_ADDRH
OTP address high byte register offset.
Definition smscusb.h:59
#define SMSCUSB_OTP_POWER
OTP power register offset.
Definition smscusb.h:55
#define SMSCUSB_E2P_DATA_GET(e2p_data)
EEPROM data.
Definition smscusb.h:45
#define SMSCUSB_OTP_STATUS_BUSY
OTP busy.
Definition smscusb.h:79
#define SMSCUSB_E2P_CMD
EEPROM command register offset.
Definition smscusb.h:38
#define SMSCUSB_MII_ACCESS_MIIBZY
MII busy.
Definition smscusb.h:101
#define SMSCUSB_ADDR_FILTH_VALID
Address valid.
Definition smscusb.h:133
#define SMSCUSB_RX_ADDRL
MAC receive address low register offset.
Definition smscusb.h:129
#define SMSCUSB_REGISTER_READ
Register read command.
Definition smscusb.h:28
#define SMSCUSB_REGISTER_WRITE
Register write command.
Definition smscusb.h:23
#define SMSCUSB_EEPROM_MAC
MAC address EEPROM address.
Definition smscusb.h:49
#define SMSCUSB_EEPROM_MAX_WAIT_MS
Maximum time to wait for EEPROM (in milliseconds)
Definition smscusb.h:52
#define SMSCUSB_MII_ACCESS_MIIRINDA(addr)
MII register.
Definition smscusb.h:99
#define SMSCUSB_OTP_POWER_DOWN
OTP power down.
Definition smscusb.h:56
#define SMSCUSB_ADDR_FILTH(n)
MAC address perfect filter N high register offset.
Definition smscusb.h:132
#define SMSCUSB_OTP_1_SIG
OTP layout 1 signature.
Definition smscusb.h:85
#define SMSCUSB_OTP_STATUS
OTP status register offset.
Definition smscusb.h:78
#define SMSCUSB_E2P_DATA
EEPROM data register offset.
Definition smscusb.h:44
#define SMSCUSB_E2P_CMD_EPC_BSY
EPC busy.
Definition smscusb.h:39
#define SMSCUSB_E2P_CMD_EPC_ADDR(addr)
EPC address.
Definition smscusb.h:41
#define SMSCUSB_OTP_1_MAC
OTP layout 1 MAC address offset.
Definition smscusb.h:88
#define SMSCUSB_ADDR_FILTL(n)
MAC address perfect filter N low register offset.
Definition smscusb.h:136
#define SMSCUSB_OTP_MAX_WAIT_MS
Maximum time to wait for OTP (in milliseconds)
Definition smscusb.h:82
#define SMSCUSB_OTP_GO_GO
Initiate command.
Definition smscusb.h:75
static int smscusb_readl(struct smscusb_device *smscusb, unsigned int address, uint32_t *value)
Read register.
Definition smscusb.h:201
#define SMSCUSB_MII_ACCESS
MII access register offset.
Definition smscusb.h:97
#define SMSCUSB_MII_ACCESS_MIIWNR
MII write.
Definition smscusb.h:100
#define SMSCUSB_OTP_ADDRL
OTP address low byte register offset.
Definition smscusb.h:62
#define SMSCUSB_E2P_CMD_EPC_CMD_READ
READ command.
Definition smscusb.h:40
static int smscusb_writel(struct smscusb_device *smscusb, unsigned int address, uint32_t value)
Write register.
Definition smscusb.h:180
#define SMSCUSB_OTP_2_SIG
OTP layout 2 signature.
Definition smscusb.h:91
#define SMSCUSB_RX_ADDRH
MAC receive address high register offset.
Definition smscusb.h:126
#define SMSCUSB_MII_DATA_GET(mii_data)
Get data.
Definition smscusb.h:106
#define SMSCUSB_OTP_CMD_READ
Read command.
Definition smscusb.h:71
#define SMSCUSB_OTP_CMD
OTP command selection register offset.
Definition smscusb.h:70
#define SMSCUSB_MII_DATA_SET(data)
Set data.
Definition smscusb.h:105
#define SMSCUSB_OTP_DATA
OTP data register offset.
Definition smscusb.h:65
#define SMSCUSB_OTP_DATA_GET(otp_data)
OTP data.
Definition smscusb.h:66
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
An MII interface.
Definition mii.h:44
MII interface operations.
Definition mii.h:19
A network device.
Definition netdevice.h:353
A data structure for storing profiling information.
Definition profile.h:27
An SMSC USB device.
Definition smscusb.h:145
struct usb_device * usb
USB device.
Definition smscusb.h:147
struct net_device * netdev
Network device.
Definition smscusb.h:151
struct mii_device mii
MII device.
Definition smscusb.h:157
uint16_t mii_base
MII register base.
Definition smscusb.h:159
uint32_t int_sts
Interrupt status.
Definition smscusb.h:163
uint16_t phy_source
PHY interrupt source register.
Definition smscusb.h:161
struct mii_interface mdio
MII interface.
Definition smscusb.h:155
struct usbnet_device usbnet
USB network device.
Definition smscusb.h:153
Interrupt packet format.
Definition smscusb.h:139
USB endpoint driver operations.
Definition usb.h:489
A USB endpoint.
Definition usb.h:404
int open
Endpoint is open.
Definition usb.h:419
struct usb_endpoint out
Bulk OUT endpoint.
Definition usbnet.h:32
struct usb_endpoint intr
Interrupt endpoint.
Definition usbnet.h:28
void mdelay(unsigned long msecs)
Delay for a fixed number of milliseconds.
Definition timer.c:79
MAC address.
Definition smscusb.h:113
int usb_control(struct usb_device *usb, unsigned int request, unsigned int value, unsigned int index, void *data, size_t len)
Issue USB control transaction.
Definition usb.c:784
USB network devices.