1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2013 Gerhard Sittig <gsi@denx.de> 4 * based on the U-Boot Asix driver as well as information 5 * from the Linux Moschip driver 6 */ 7 8 /* 9 * MOSCHIP MCS7830 based (7730/7830/7832) USB 2.0 Ethernet Devices 10 */ 11 12 #include <common.h> 13 #include <dm.h> 14 #include <errno.h> 15 #include <linux/mii.h> 16 #include <malloc.h> 17 #include <memalign.h> 18 #include <usb.h> 19 20 #include "usb_ether.h" 21 22 #define MCS7830_BASE_NAME "mcs" 23 24 #define USBCALL_TIMEOUT 1000 25 #define LINKSTATUS_TIMEOUT 5000 /* link status, connect timeout */ 26 #define LINKSTATUS_TIMEOUT_RES 50 /* link status, resolution in msec */ 27 28 #define MCS7830_RX_URB_SIZE 2048 29 30 /* command opcodes */ 31 #define MCS7830_WR_BREQ 0x0d 32 #define MCS7830_RD_BREQ 0x0e 33 34 /* register layout, numerical offset specs for USB API calls */ 35 struct mcs7830_regs { 36 uint8_t multicast_hashes[8]; 37 uint8_t packet_gap[2]; 38 uint8_t phy_data[2]; 39 uint8_t phy_command[2]; 40 uint8_t configuration; 41 uint8_t ether_address[6]; 42 uint8_t frame_drop_count; 43 uint8_t pause_threshold; 44 }; 45 #define REG_MULTICAST_HASH offsetof(struct mcs7830_regs, multicast_hashes) 46 #define REG_PHY_DATA offsetof(struct mcs7830_regs, phy_data) 47 #define REG_PHY_CMD offsetof(struct mcs7830_regs, phy_command) 48 #define REG_CONFIG offsetof(struct mcs7830_regs, configuration) 49 #define REG_ETHER_ADDR offsetof(struct mcs7830_regs, ether_address) 50 #define REG_FRAME_DROP_COUNTER offsetof(struct mcs7830_regs, frame_drop_count) 51 #define REG_PAUSE_THRESHOLD offsetof(struct mcs7830_regs, pause_threshold) 52 53 /* bit masks and default values for the above registers */ 54 #define PHY_CMD1_READ 0x40 55 #define PHY_CMD1_WRITE 0x20 56 #define PHY_CMD1_PHYADDR 0x01 57 58 #define PHY_CMD2_PEND 0x80 59 #define PHY_CMD2_READY 0x40 60 61 #define CONF_CFG 0x80 62 #define CONF_SPEED100 0x40 63 #define CONF_FDX_ENABLE 0x20 64 #define CONF_RXENABLE 0x10 65 #define CONF_TXENABLE 0x08 66 #define CONF_SLEEPMODE 0x04 67 #define CONF_ALLMULTICAST 0x02 68 #define CONF_PROMISCUOUS 0x01 69 70 #define PAUSE_THRESHOLD_DEFAULT 0 71 72 /* bit masks for the status byte which follows received ethernet frames */ 73 #define STAT_RX_FRAME_CORRECT 0x20 74 #define STAT_RX_LARGE_FRAME 0x10 75 #define STAT_RX_CRC_ERROR 0x08 76 #define STAT_RX_ALIGNMENT_ERROR 0x04 77 #define STAT_RX_LENGTH_ERROR 0x02 78 #define STAT_RX_SHORT_FRAME 0x01 79 80 /* 81 * struct mcs7830_private - private driver data for an individual adapter 82 * @config: shadow for the network adapter's configuration register 83 * @mchash: shadow for the network adapter's multicast hash registers 84 */ 85 struct mcs7830_private { 86 #ifdef CONFIG_DM_ETH 87 uint8_t rx_buf[MCS7830_RX_URB_SIZE]; 88 struct ueth_data ueth; 89 #endif 90 uint8_t config; 91 uint8_t mchash[8]; 92 }; 93 94 /* 95 * mcs7830_read_reg() - read a register of the network adapter 96 * @udev: network device to read from 97 * @idx: index of the register to start reading from 98 * @size: number of bytes to read 99 * @data: buffer to read into 100 * Return: zero upon success, negative upon error 101 */ 102 static int mcs7830_read_reg(struct usb_device *udev, uint8_t idx, 103 uint16_t size, void *data) 104 { 105 int len; 106 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size); 107 108 debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); 109 110 len = usb_control_msg(udev, 111 usb_rcvctrlpipe(udev, 0), 112 MCS7830_RD_BREQ, 113 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 114 0, idx, buf, size, 115 USBCALL_TIMEOUT); 116 if (len != size) { 117 debug("%s() len=%d != sz=%d\n", __func__, len, size); 118 return -EIO; 119 } 120 memcpy(data, buf, size); 121 return 0; 122 } 123 124 /* 125 * mcs7830_write_reg() - write a register of the network adapter 126 * @udev: network device to write to 127 * @idx: index of the register to start writing to 128 * @size: number of bytes to write 129 * @data: buffer holding the data to write 130 * Return: zero upon success, negative upon error 131 */ 132 static int mcs7830_write_reg(struct usb_device *udev, uint8_t idx, 133 uint16_t size, void *data) 134 { 135 int len; 136 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size); 137 138 debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); 139 140 memcpy(buf, data, size); 141 len = usb_control_msg(udev, 142 usb_sndctrlpipe(udev, 0), 143 MCS7830_WR_BREQ, 144 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 145 0, idx, buf, size, 146 USBCALL_TIMEOUT); 147 if (len != size) { 148 debug("%s() len=%d != sz=%d\n", __func__, len, size); 149 return -EIO; 150 } 151 return 0; 152 } 153 154 /* 155 * mcs7830_phy_emit_wait() - emit PHY read/write access, wait for its execution 156 * @udev: network device to talk to 157 * @rwflag: PHY_CMD1_READ or PHY_CMD1_WRITE opcode 158 * @index: number of the PHY register to read or write 159 * Return: zero upon success, negative upon error 160 */ 161 static int mcs7830_phy_emit_wait(struct usb_device *udev, 162 uint8_t rwflag, uint8_t index) 163 { 164 int rc; 165 int retry; 166 uint8_t cmd[2]; 167 168 /* send the PHY read/write request */ 169 cmd[0] = rwflag | PHY_CMD1_PHYADDR; 170 cmd[1] = PHY_CMD2_PEND | (index & 0x1f); 171 rc = mcs7830_write_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd); 172 if (rc < 0) 173 return rc; 174 175 /* wait for the response to become available (usually < 1ms) */ 176 retry = 10; 177 do { 178 rc = mcs7830_read_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd); 179 if (rc < 0) 180 return rc; 181 if (cmd[1] & PHY_CMD2_READY) 182 return 0; 183 if (!retry--) 184 return -ETIMEDOUT; 185 mdelay(1); 186 } while (1); 187 /* UNREACH */ 188 } 189 190 /* 191 * mcs7830_read_phy() - read a PHY register of the network adapter 192 * @udev: network device to read from 193 * @index: index of the PHY register to read from 194 * Return: non-negative 16bit register content, negative upon error 195 */ 196 static int mcs7830_read_phy(struct usb_device *udev, uint8_t index) 197 { 198 int rc; 199 uint16_t val; 200 201 /* issue the PHY read request and wait for its execution */ 202 rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_READ, index); 203 if (rc < 0) 204 return rc; 205 206 /* fetch the PHY data which was read */ 207 rc = mcs7830_read_reg(udev, REG_PHY_DATA, sizeof(val), &val); 208 if (rc < 0) 209 return rc; 210 rc = le16_to_cpu(val); 211 debug("%s(%d) => 0x%04X\n", __func__, index, rc); 212 return rc; 213 } 214 215 /* 216 * mcs7830_write_phy() - write a PHY register of the network adapter 217 * @udev: network device to write to 218 * @index: index of the PHY register to write to 219 * @val: value to write to the PHY register 220 * Return: zero upon success, negative upon error 221 */ 222 static int mcs7830_write_phy(struct usb_device *udev, uint8_t index, 223 uint16_t val) 224 { 225 int rc; 226 227 debug("%s(%d, 0x%04X)\n", __func__, index, val); 228 229 /* setup the PHY data which is to get written */ 230 val = cpu_to_le16(val); 231 rc = mcs7830_write_reg(udev, REG_PHY_DATA, sizeof(val), &val); 232 if (rc < 0) 233 return rc; 234 235 /* issue the PHY write request and wait for its execution */ 236 rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_WRITE, index); 237 if (rc < 0) 238 return rc; 239 240 return 0; 241 } 242 243 /* 244 * mcs7830_write_config() - write to the network adapter's config register 245 * @udev: network device to write to 246 * @priv: private data 247 * Return: zero upon success, negative upon error 248 * 249 * the data which gets written is taken from the shadow config register 250 * within the device driver's private data 251 */ 252 static int mcs7830_write_config(struct usb_device *udev, 253 struct mcs7830_private *priv) 254 { 255 int rc; 256 257 debug("%s()\n", __func__); 258 259 rc = mcs7830_write_reg(udev, REG_CONFIG, 260 sizeof(priv->config), &priv->config); 261 if (rc < 0) { 262 debug("writing config to adapter failed\n"); 263 return rc; 264 } 265 266 return 0; 267 } 268 269 /* 270 * mcs7830_write_mchash() - write the network adapter's multicast filter 271 * @udev: network device to write to 272 * @priv: private data 273 * Return: zero upon success, negative upon error 274 * 275 * the data which gets written is taken from the shadow multicast hashes 276 * within the device driver's private data 277 */ 278 static int mcs7830_write_mchash(struct usb_device *udev, 279 struct mcs7830_private *priv) 280 { 281 int rc; 282 283 debug("%s()\n", __func__); 284 285 rc = mcs7830_write_reg(udev, REG_MULTICAST_HASH, 286 sizeof(priv->mchash), &priv->mchash); 287 if (rc < 0) { 288 debug("writing multicast hash to adapter failed\n"); 289 return rc; 290 } 291 292 return 0; 293 } 294 295 /* 296 * mcs7830_set_autoneg() - setup and trigger ethernet link autonegotiation 297 * @udev: network device to run link negotiation on 298 * Return: zero upon success, negative upon error 299 * 300 * the routine advertises available media and starts autonegotiation 301 */ 302 static int mcs7830_set_autoneg(struct usb_device *udev) 303 { 304 int adv, flg; 305 int rc; 306 307 debug("%s()\n", __func__); 308 309 /* 310 * algorithm taken from the Linux driver, which took it from 311 * "the original mcs7830 version 1.4 driver": 312 * 313 * enable all media, reset BMCR, enable auto neg, restart 314 * auto neg while keeping the enable auto neg flag set 315 */ 316 317 adv = ADVERTISE_PAUSE_CAP | ADVERTISE_ALL | ADVERTISE_CSMA; 318 rc = mcs7830_write_phy(udev, MII_ADVERTISE, adv); 319 320 flg = 0; 321 if (!rc) 322 rc = mcs7830_write_phy(udev, MII_BMCR, flg); 323 324 flg |= BMCR_ANENABLE; 325 if (!rc) 326 rc = mcs7830_write_phy(udev, MII_BMCR, flg); 327 328 flg |= BMCR_ANRESTART; 329 if (!rc) 330 rc = mcs7830_write_phy(udev, MII_BMCR, flg); 331 332 return rc; 333 } 334 335 /* 336 * mcs7830_get_rev() - identify a network adapter's chip revision 337 * @udev: network device to identify 338 * Return: non-negative number, reflecting the revision number 339 * 340 * currently, only "rev C and higher" and "below rev C" are needed, so 341 * the return value is #1 for "below rev C", and #2 for "rev C and above" 342 */ 343 static int mcs7830_get_rev(struct usb_device *udev) 344 { 345 uint8_t buf[2]; 346 int rc; 347 int rev; 348 349 /* register 22 is readable in rev C and higher */ 350 rc = mcs7830_read_reg(udev, REG_FRAME_DROP_COUNTER, sizeof(buf), buf); 351 if (rc < 0) 352 rev = 1; 353 else 354 rev = 2; 355 debug("%s() rc=%d, rev=%d\n", __func__, rc, rev); 356 return rev; 357 } 358 359 /* 360 * mcs7830_apply_fixup() - identify an adapter and potentially apply fixups 361 * @udev: network device to identify and apply fixups to 362 * Return: zero upon success (no errors emitted from here) 363 * 364 * this routine identifies the network adapter's chip revision, and applies 365 * fixups for known issues 366 */ 367 static int mcs7830_apply_fixup(struct usb_device *udev) 368 { 369 int rev; 370 int i; 371 uint8_t thr; 372 373 rev = mcs7830_get_rev(udev); 374 debug("%s() rev=%d\n", __func__, rev); 375 376 /* 377 * rev C requires setting the pause threshold (the Linux driver 378 * is inconsistent, the implementation does it for "rev C 379 * exactly", the introductory comment says "rev C and above") 380 */ 381 if (rev == 2) { 382 debug("%s: applying rev C fixup\n", __func__); 383 thr = PAUSE_THRESHOLD_DEFAULT; 384 for (i = 0; i < 2; i++) { 385 (void)mcs7830_write_reg(udev, REG_PAUSE_THRESHOLD, 386 sizeof(thr), &thr); 387 mdelay(1); 388 } 389 } 390 391 return 0; 392 } 393 394 /* 395 * mcs7830_basic_reset() - bring the network adapter into a known first state 396 * @eth: network device to act upon 397 * Return: zero upon success, negative upon error 398 * 399 * this routine initializes the network adapter such that subsequent invocations 400 * of the interface callbacks can exchange ethernet frames; link negotiation is 401 * triggered from here already and continues in background 402 */ 403 static int mcs7830_basic_reset(struct usb_device *udev, 404 struct mcs7830_private *priv) 405 { 406 int rc; 407 408 debug("%s()\n", __func__); 409 410 /* 411 * comment from the respective Linux driver, which 412 * unconditionally sets the ALLMULTICAST flag as well: 413 * should not be needed, but does not work otherwise 414 */ 415 priv->config = CONF_TXENABLE; 416 priv->config |= CONF_ALLMULTICAST; 417 418 rc = mcs7830_set_autoneg(udev); 419 if (rc < 0) { 420 pr_err("setting autoneg failed\n"); 421 return rc; 422 } 423 424 rc = mcs7830_write_mchash(udev, priv); 425 if (rc < 0) { 426 pr_err("failed to set multicast hash\n"); 427 return rc; 428 } 429 430 rc = mcs7830_write_config(udev, priv); 431 if (rc < 0) { 432 pr_err("failed to set configuration\n"); 433 return rc; 434 } 435 436 rc = mcs7830_apply_fixup(udev); 437 if (rc < 0) { 438 pr_err("fixup application failed\n"); 439 return rc; 440 } 441 442 return 0; 443 } 444 445 /* 446 * mcs7830_read_mac() - read an ethernet adapter's MAC address 447 * @udev: network device to read from 448 * @enetaddr: place to put ethernet MAC address 449 * Return: zero upon success, negative upon error 450 * 451 * this routine fetches the MAC address stored within the ethernet adapter, 452 * and stores it in the ethernet interface's data structure 453 */ 454 static int mcs7830_read_mac(struct usb_device *udev, unsigned char enetaddr[]) 455 { 456 int rc; 457 uint8_t buf[ETH_ALEN]; 458 459 debug("%s()\n", __func__); 460 461 rc = mcs7830_read_reg(udev, REG_ETHER_ADDR, ETH_ALEN, buf); 462 if (rc < 0) { 463 debug("reading MAC from adapter failed\n"); 464 return rc; 465 } 466 467 memcpy(enetaddr, buf, ETH_ALEN); 468 return 0; 469 } 470 471 static int mcs7830_write_mac_common(struct usb_device *udev, 472 unsigned char enetaddr[]) 473 { 474 int rc; 475 476 debug("%s()\n", __func__); 477 478 rc = mcs7830_write_reg(udev, REG_ETHER_ADDR, ETH_ALEN, enetaddr); 479 if (rc < 0) { 480 debug("writing MAC to adapter failed\n"); 481 return rc; 482 } 483 return 0; 484 } 485 486 static int mcs7830_init_common(struct usb_device *udev) 487 { 488 int timeout; 489 int have_link; 490 491 debug("%s()\n", __func__); 492 493 timeout = 0; 494 do { 495 have_link = mcs7830_read_phy(udev, MII_BMSR) & BMSR_LSTATUS; 496 if (have_link) 497 break; 498 udelay(LINKSTATUS_TIMEOUT_RES * 1000); 499 timeout += LINKSTATUS_TIMEOUT_RES; 500 } while (timeout < LINKSTATUS_TIMEOUT); 501 if (!have_link) { 502 debug("ethernet link is down\n"); 503 return -ETIMEDOUT; 504 } 505 return 0; 506 } 507 508 static int mcs7830_send_common(struct ueth_data *ueth, void *packet, 509 int length) 510 { 511 struct usb_device *udev = ueth->pusb_dev; 512 int rc; 513 int gotlen; 514 /* there is a status byte after the ethernet frame */ 515 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, PKTSIZE + sizeof(uint8_t)); 516 517 memcpy(buf, packet, length); 518 rc = usb_bulk_msg(udev, 519 usb_sndbulkpipe(udev, ueth->ep_out), 520 &buf[0], length, &gotlen, 521 USBCALL_TIMEOUT); 522 debug("%s() TX want len %d, got len %d, rc %d\n", 523 __func__, length, gotlen, rc); 524 return rc; 525 } 526 527 static int mcs7830_recv_common(struct ueth_data *ueth, uint8_t *buf) 528 { 529 int rc, wantlen, gotlen; 530 uint8_t sts; 531 532 debug("%s()\n", __func__); 533 534 /* fetch input data from the adapter */ 535 wantlen = MCS7830_RX_URB_SIZE; 536 rc = usb_bulk_msg(ueth->pusb_dev, 537 usb_rcvbulkpipe(ueth->pusb_dev, ueth->ep_in), 538 &buf[0], wantlen, &gotlen, 539 USBCALL_TIMEOUT); 540 debug("%s() RX want len %d, got len %d, rc %d\n", 541 __func__, wantlen, gotlen, rc); 542 if (rc != 0) { 543 pr_err("RX: failed to receive\n"); 544 return rc; 545 } 546 if (gotlen > wantlen) { 547 pr_err("RX: got too many bytes (%d)\n", gotlen); 548 return -EIO; 549 } 550 551 /* 552 * the bulk message that we received from USB contains exactly 553 * one ethernet frame and a trailing status byte 554 */ 555 if (gotlen < sizeof(sts)) 556 return -EIO; 557 gotlen -= sizeof(sts); 558 sts = buf[gotlen]; 559 560 if (sts == STAT_RX_FRAME_CORRECT) { 561 debug("%s() got a frame, len=%d\n", __func__, gotlen); 562 return gotlen; 563 } 564 565 debug("RX: frame error (sts 0x%02X, %s %s %s %s %s)\n", 566 sts, 567 (sts & STAT_RX_LARGE_FRAME) ? "large" : "-", 568 (sts & STAT_RX_LENGTH_ERROR) ? "length" : "-", 569 (sts & STAT_RX_SHORT_FRAME) ? "short" : "-", 570 (sts & STAT_RX_CRC_ERROR) ? "crc" : "-", 571 (sts & STAT_RX_ALIGNMENT_ERROR) ? "align" : "-"); 572 return -EIO; 573 } 574 575 #ifndef CONFIG_DM_ETH 576 /* 577 * mcs7830_init() - network interface's init callback 578 * @udev: network device to initialize 579 * @bd: board information 580 * Return: zero upon success, negative upon error 581 * 582 * after initial setup during probe() and get_info(), this init() callback 583 * ensures that the link is up and subsequent send() and recv() calls can 584 * exchange ethernet frames 585 */ 586 static int mcs7830_init(struct eth_device *eth, bd_t *bd) 587 { 588 struct ueth_data *dev = eth->priv; 589 590 return mcs7830_init_common(dev->pusb_dev); 591 } 592 593 /* 594 * mcs7830_send() - network interface's send callback 595 * @eth: network device to send the frame from 596 * @packet: ethernet frame content 597 * @length: ethernet frame length 598 * Return: zero upon success, negative upon error 599 * 600 * this routine send an ethernet frame out of the network interface 601 */ 602 static int mcs7830_send(struct eth_device *eth, void *packet, int length) 603 { 604 struct ueth_data *dev = eth->priv; 605 606 return mcs7830_send_common(dev, packet, length); 607 } 608 609 /* 610 * mcs7830_recv() - network interface's recv callback 611 * @eth: network device to receive frames from 612 * Return: zero upon success, negative upon error 613 * 614 * this routine checks for available ethernet frames that the network 615 * interface might have received, and notifies the network stack 616 */ 617 static int mcs7830_recv(struct eth_device *eth) 618 { 619 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, MCS7830_RX_URB_SIZE); 620 struct ueth_data *ueth = eth->priv; 621 int len; 622 623 len = mcs7830_recv_common(ueth, buf); 624 if (len >= 0) { 625 net_process_received_packet(buf, len); 626 return 0; 627 } 628 629 return len; 630 } 631 632 /* 633 * mcs7830_halt() - network interface's halt callback 634 * @eth: network device to cease operation of 635 * Return: none 636 * 637 * this routine is supposed to undo the effect of previous initialization and 638 * ethernet frames exchange; in this implementation it's a NOP 639 */ 640 static void mcs7830_halt(struct eth_device *eth) 641 { 642 debug("%s()\n", __func__); 643 } 644 645 /* 646 * mcs7830_write_mac() - write an ethernet adapter's MAC address 647 * @eth: network device to write to 648 * Return: zero upon success, negative upon error 649 * 650 * this routine takes the MAC address from the ethernet interface's data 651 * structure, and writes it into the ethernet adapter such that subsequent 652 * exchange of ethernet frames uses this address 653 */ 654 static int mcs7830_write_mac(struct eth_device *eth) 655 { 656 struct ueth_data *ueth = eth->priv; 657 658 return mcs7830_write_mac_common(ueth->pusb_dev, eth->enetaddr); 659 } 660 661 /* 662 * mcs7830_iface_idx - index of detected network interfaces 663 * 664 * this counter keeps track of identified supported interfaces, 665 * to assign unique names as more interfaces are found 666 */ 667 static int mcs7830_iface_idx; 668 669 /* 670 * mcs7830_eth_before_probe() - network driver's before_probe callback 671 * Return: none 672 * 673 * this routine initializes driver's internal data in preparation of 674 * subsequent probe callbacks 675 */ 676 void mcs7830_eth_before_probe(void) 677 { 678 mcs7830_iface_idx = 0; 679 } 680 681 /* 682 * struct mcs7830_dongle - description of a supported Moschip ethernet dongle 683 * @vendor: 16bit USB vendor identification 684 * @product: 16bit USB product identification 685 * 686 * this structure describes a supported USB ethernet dongle by means of the 687 * vendor and product codes found during USB enumeration; no flags are held 688 * here since all supported dongles have identical behaviour, and required 689 * fixups get determined at runtime, such that no manual configuration is 690 * needed 691 */ 692 struct mcs7830_dongle { 693 uint16_t vendor; 694 uint16_t product; 695 }; 696 697 /* 698 * mcs7830_dongles - the list of supported Moschip based USB ethernet dongles 699 */ 700 static const struct mcs7830_dongle mcs7830_dongles[] = { 701 { 0x9710, 0x7832, }, /* Moschip 7832 */ 702 { 0x9710, 0x7830, }, /* Moschip 7830 */ 703 { 0x9710, 0x7730, }, /* Moschip 7730 */ 704 { 0x0df6, 0x0021, }, /* Sitecom LN 30 */ 705 }; 706 707 /* 708 * mcs7830_eth_probe() - network driver's probe callback 709 * @dev: detected USB device to check 710 * @ifnum: detected USB interface to check 711 * @ss: USB ethernet data structure to fill in upon match 712 * Return: #1 upon match, #0 upon mismatch or error 713 * 714 * this routine checks whether the found USB device is supported by 715 * this ethernet driver, and upon match fills in the USB ethernet 716 * data structure which later is passed to the get_info callback 717 */ 718 int mcs7830_eth_probe(struct usb_device *dev, unsigned int ifnum, 719 struct ueth_data *ss) 720 { 721 struct usb_interface *iface; 722 struct usb_interface_descriptor *iface_desc; 723 int i; 724 struct mcs7830_private *priv; 725 int ep_in_found, ep_out_found, ep_intr_found; 726 727 debug("%s()\n", __func__); 728 729 /* iterate the list of supported dongles */ 730 iface = &dev->config.if_desc[ifnum]; 731 iface_desc = &iface->desc; 732 for (i = 0; i < ARRAY_SIZE(mcs7830_dongles); i++) { 733 if (dev->descriptor.idVendor == mcs7830_dongles[i].vendor && 734 dev->descriptor.idProduct == mcs7830_dongles[i].product) 735 break; 736 } 737 if (i == ARRAY_SIZE(mcs7830_dongles)) 738 return 0; 739 debug("detected USB ethernet device: %04X:%04X\n", 740 dev->descriptor.idVendor, dev->descriptor.idProduct); 741 742 /* fill in driver private data */ 743 priv = calloc(1, sizeof(*priv)); 744 if (!priv) 745 return 0; 746 747 /* fill in the ueth_data structure, attach private data */ 748 memset(ss, 0, sizeof(*ss)); 749 ss->ifnum = ifnum; 750 ss->pusb_dev = dev; 751 ss->subclass = iface_desc->bInterfaceSubClass; 752 ss->protocol = iface_desc->bInterfaceProtocol; 753 ss->dev_priv = priv; 754 755 /* 756 * a minimum of three endpoints is expected: in (bulk), 757 * out (bulk), and interrupt; ignore all others 758 */ 759 ep_in_found = ep_out_found = ep_intr_found = 0; 760 for (i = 0; i < iface_desc->bNumEndpoints; i++) { 761 uint8_t eptype, epaddr; 762 bool is_input; 763 764 eptype = iface->ep_desc[i].bmAttributes; 765 eptype &= USB_ENDPOINT_XFERTYPE_MASK; 766 767 epaddr = iface->ep_desc[i].bEndpointAddress; 768 is_input = epaddr & USB_DIR_IN; 769 epaddr &= USB_ENDPOINT_NUMBER_MASK; 770 771 if (eptype == USB_ENDPOINT_XFER_BULK) { 772 if (is_input && !ep_in_found) { 773 ss->ep_in = epaddr; 774 ep_in_found++; 775 } 776 if (!is_input && !ep_out_found) { 777 ss->ep_out = epaddr; 778 ep_out_found++; 779 } 780 } 781 782 if (eptype == USB_ENDPOINT_XFER_INT) { 783 if (is_input && !ep_intr_found) { 784 ss->ep_int = epaddr; 785 ss->irqinterval = iface->ep_desc[i].bInterval; 786 ep_intr_found++; 787 } 788 } 789 } 790 debug("endpoints: in %d, out %d, intr %d\n", 791 ss->ep_in, ss->ep_out, ss->ep_int); 792 793 /* apply basic sanity checks */ 794 if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) || 795 !ss->ep_in || !ss->ep_out || !ss->ep_int) { 796 debug("device probe incomplete\n"); 797 return 0; 798 } 799 800 dev->privptr = ss; 801 return 1; 802 } 803 804 /* 805 * mcs7830_eth_get_info() - network driver's get_info callback 806 * @dev: detected USB device 807 * @ss: USB ethernet data structure filled in at probe() 808 * @eth: ethernet interface data structure to fill in 809 * Return: #1 upon success, #0 upon error 810 * 811 * this routine registers the mandatory init(), send(), recv(), and 812 * halt() callbacks with the ethernet interface, can register the 813 * optional write_hwaddr() callback with the ethernet interface, 814 * and initiates configuration of the interface such that subsequent 815 * calls to those callbacks results in network communication 816 */ 817 int mcs7830_eth_get_info(struct usb_device *dev, struct ueth_data *ss, 818 struct eth_device *eth) 819 { 820 debug("%s()\n", __func__); 821 if (!eth) { 822 debug("%s: missing parameter.\n", __func__); 823 return 0; 824 } 825 826 snprintf(eth->name, sizeof(eth->name), "%s%d", 827 MCS7830_BASE_NAME, mcs7830_iface_idx++); 828 eth->init = mcs7830_init; 829 eth->send = mcs7830_send; 830 eth->recv = mcs7830_recv; 831 eth->halt = mcs7830_halt; 832 eth->write_hwaddr = mcs7830_write_mac; 833 eth->priv = ss; 834 835 if (mcs7830_basic_reset(ss->pusb_dev, ss->dev_priv)) 836 return 0; 837 838 if (mcs7830_read_mac(ss->pusb_dev, eth->enetaddr)) 839 return 0; 840 debug("MAC %pM\n", eth->enetaddr); 841 842 return 1; 843 } 844 #endif 845 846 847 #ifdef CONFIG_DM_ETH 848 static int mcs7830_eth_start(struct udevice *dev) 849 { 850 struct usb_device *udev = dev_get_parent_priv(dev); 851 852 return mcs7830_init_common(udev); 853 } 854 855 void mcs7830_eth_stop(struct udevice *dev) 856 { 857 debug("** %s()\n", __func__); 858 } 859 860 int mcs7830_eth_send(struct udevice *dev, void *packet, int length) 861 { 862 struct mcs7830_private *priv = dev_get_priv(dev); 863 struct ueth_data *ueth = &priv->ueth; 864 865 return mcs7830_send_common(ueth, packet, length); 866 } 867 868 int mcs7830_eth_recv(struct udevice *dev, int flags, uchar **packetp) 869 { 870 struct mcs7830_private *priv = dev_get_priv(dev); 871 struct ueth_data *ueth = &priv->ueth; 872 int len; 873 874 len = mcs7830_recv_common(ueth, priv->rx_buf); 875 *packetp = priv->rx_buf; 876 877 return len; 878 } 879 880 static int mcs7830_free_pkt(struct udevice *dev, uchar *packet, int packet_len) 881 { 882 struct mcs7830_private *priv = dev_get_priv(dev); 883 884 packet_len = ALIGN(packet_len, 4); 885 usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len); 886 887 return 0; 888 } 889 890 int mcs7830_write_hwaddr(struct udevice *dev) 891 { 892 struct usb_device *udev = dev_get_parent_priv(dev); 893 struct eth_pdata *pdata = dev_get_platdata(dev); 894 895 return mcs7830_write_mac_common(udev, pdata->enetaddr); 896 } 897 898 static int mcs7830_eth_probe(struct udevice *dev) 899 { 900 struct usb_device *udev = dev_get_parent_priv(dev); 901 struct mcs7830_private *priv = dev_get_priv(dev); 902 struct eth_pdata *pdata = dev_get_platdata(dev); 903 struct ueth_data *ueth = &priv->ueth; 904 905 if (mcs7830_basic_reset(udev, priv)) 906 return 0; 907 908 if (mcs7830_read_mac(udev, pdata->enetaddr)) 909 return 0; 910 911 return usb_ether_register(dev, ueth, MCS7830_RX_URB_SIZE); 912 } 913 914 static const struct eth_ops mcs7830_eth_ops = { 915 .start = mcs7830_eth_start, 916 .send = mcs7830_eth_send, 917 .recv = mcs7830_eth_recv, 918 .free_pkt = mcs7830_free_pkt, 919 .stop = mcs7830_eth_stop, 920 .write_hwaddr = mcs7830_write_hwaddr, 921 }; 922 923 U_BOOT_DRIVER(mcs7830_eth) = { 924 .name = "mcs7830_eth", 925 .id = UCLASS_ETH, 926 .probe = mcs7830_eth_probe, 927 .ops = &mcs7830_eth_ops, 928 .priv_auto_alloc_size = sizeof(struct mcs7830_private), 929 .platdata_auto_alloc_size = sizeof(struct eth_pdata), 930 .flags = DM_FLAG_ALLOC_PRIV_DMA, 931 }; 932 933 static const struct usb_device_id mcs7830_eth_id_table[] = { 934 { USB_DEVICE(0x9710, 0x7832) }, /* Moschip 7832 */ 935 { USB_DEVICE(0x9710, 0x7830), }, /* Moschip 7830 */ 936 { USB_DEVICE(0x9710, 0x7730), }, /* Moschip 7730 */ 937 { USB_DEVICE(0x0df6, 0x0021), }, /* Sitecom LN 30 */ 938 { } /* Terminating entry */ 939 }; 940 941 U_BOOT_USB_DEVICE(mcs7830_eth, mcs7830_eth_id_table); 942 #endif 943