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