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 <log.h> 16#include <net.h> 17#include <linux/delay.h> 18#include <linux/mii.h> 19#include <malloc.h> 20#include <memalign.h> 21#include <usb.h> 22#include <linux/printk.h> 23 24#include "usb_ether.h" 25 26#define MCS7830_BASE_NAME "mcs" 27 28#define USBCALL_TIMEOUT 1000 29#define LINKSTATUS_TIMEOUT 5000 /* link status, connect timeout */ 30#define LINKSTATUS_TIMEOUT_RES 50 /* link status, resolution in msec */ 31 32#define MCS7830_RX_URB_SIZE 2048 33 34/* command opcodes */ 35#define MCS7830_WR_BREQ 0x0d 36#define MCS7830_RD_BREQ 0x0e 37 38/* register layout, numerical offset specs for USB API calls */ 39struct mcs7830_regs { 40 uint8_t multicast_hashes[8]; 41 uint8_t packet_gap[2]; 42 uint8_t phy_data[2]; 43 uint8_t phy_command[2]; 44 uint8_t configuration; 45 uint8_t ether_address[6]; 46 uint8_t frame_drop_count; 47 uint8_t pause_threshold; 48}; 49#define REG_MULTICAST_HASH offsetof(struct mcs7830_regs, multicast_hashes) 50#define REG_PHY_DATA offsetof(struct mcs7830_regs, phy_data) 51#define REG_PHY_CMD offsetof(struct mcs7830_regs, phy_command) 52#define REG_CONFIG offsetof(struct mcs7830_regs, configuration) 53#define REG_ETHER_ADDR offsetof(struct mcs7830_regs, ether_address) 54#define REG_FRAME_DROP_COUNTER offsetof(struct mcs7830_regs, frame_drop_count) 55#define REG_PAUSE_THRESHOLD offsetof(struct mcs7830_regs, pause_threshold) 56 57/* bit masks and default values for the above registers */ 58#define PHY_CMD1_READ 0x40 59#define PHY_CMD1_WRITE 0x20 60#define PHY_CMD1_PHYADDR 0x01 61 62#define PHY_CMD2_PEND 0x80 63#define PHY_CMD2_READY 0x40 64 65#define CONF_CFG 0x80 66#define CONF_SPEED100 0x40 67#define CONF_FDX_ENABLE 0x20 68#define CONF_RXENABLE 0x10 69#define CONF_TXENABLE 0x08 70#define CONF_SLEEPMODE 0x04 71#define CONF_ALLMULTICAST 0x02 72#define CONF_PROMISCUOUS 0x01 73 74#define PAUSE_THRESHOLD_DEFAULT 0 75 76/* bit masks for the status byte which follows received ethernet frames */ 77#define STAT_RX_FRAME_CORRECT 0x20 78#define STAT_RX_LARGE_FRAME 0x10 79#define STAT_RX_CRC_ERROR 0x08 80#define STAT_RX_ALIGNMENT_ERROR 0x04 81#define STAT_RX_LENGTH_ERROR 0x02 82#define STAT_RX_SHORT_FRAME 0x01 83 84/* 85 * struct mcs7830_private - private driver data for an individual adapter 86 * @config: shadow for the network adapter's configuration register 87 * @mchash: shadow for the network adapter's multicast hash registers 88 */ 89struct mcs7830_private { 90 uint8_t rx_buf[MCS7830_RX_URB_SIZE]; 91 struct ueth_data ueth; 92 uint8_t config; 93 uint8_t mchash[8]; 94}; 95 96/* 97 * mcs7830_read_reg() - read a register of the network adapter 98 * @udev: network device to read from 99 * @idx: index of the register to start reading from 100 * @size: number of bytes to read 101 * @data: buffer to read into 102 * Return: zero upon success, negative upon error 103 */ 104static int mcs7830_read_reg(struct usb_device *udev, uint8_t idx, 105 uint16_t size, void *data) 106{ 107 int len; 108 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size); 109 110 debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); 111 112 len = usb_control_msg(udev, 113 usb_rcvctrlpipe(udev, 0), 114 MCS7830_RD_BREQ, 115 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 116 0, idx, buf, size, 117 USBCALL_TIMEOUT); 118 if (len != size) { 119 debug("%s() len=%d != sz=%d\n", __func__, len, size); 120 return -EIO; 121 } 122 memcpy(data, buf, size); 123 return 0; 124} 125 126/* 127 * mcs7830_write_reg() - write a register of the network adapter 128 * @udev: network device to write to 129 * @idx: index of the register to start writing to 130 * @size: number of bytes to write 131 * @data: buffer holding the data to write 132 * Return: zero upon success, negative upon error 133 */ 134static int mcs7830_write_reg(struct usb_device *udev, uint8_t idx, 135 uint16_t size, void *data) 136{ 137 int len; 138 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size); 139 140 debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size); 141 142 memcpy(buf, data, size); 143 len = usb_control_msg(udev, 144 usb_sndctrlpipe(udev, 0), 145 MCS7830_WR_BREQ, 146 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 147 0, idx, buf, size, 148 USBCALL_TIMEOUT); 149 if (len != size) { 150 debug("%s() len=%d != sz=%d\n", __func__, len, size); 151 return -EIO; 152 } 153 return 0; 154} 155 156/* 157 * mcs7830_phy_emit_wait() - emit PHY read/write access, wait for its execution 158 * @udev: network device to talk to 159 * @rwflag: PHY_CMD1_READ or PHY_CMD1_WRITE opcode 160 * @index: number of the PHY register to read or write 161 * Return: zero upon success, negative upon error 162 */ 163static int mcs7830_phy_emit_wait(struct usb_device *udev, 164 uint8_t rwflag, uint8_t index) 165{ 166 int rc; 167 int retry; 168 uint8_t cmd[2]; 169 170 /* send the PHY read/write request */ 171 cmd[0] = rwflag | PHY_CMD1_PHYADDR; 172 cmd[1] = PHY_CMD2_PEND | (index & 0x1f); 173 rc = mcs7830_write_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd); 174 if (rc < 0) 175 return rc; 176 177 /* wait for the response to become available (usually < 1ms) */ 178 retry = 10; 179 do { 180 rc = mcs7830_read_reg(udev, REG_PHY_CMD, sizeof(cmd), cmd); 181 if (rc < 0) 182 return rc; 183 if (cmd[1] & PHY_CMD2_READY) 184 return 0; 185 if (!retry--) 186 return -ETIMEDOUT; 187 mdelay(1); 188 } while (1); 189 /* UNREACH */ 190} 191 192/* 193 * mcs7830_read_phy() - read a PHY register of the network adapter 194 * @udev: network device to read from 195 * @index: index of the PHY register to read from 196 * Return: non-negative 16bit register content, negative upon error 197 */ 198static int mcs7830_read_phy(struct usb_device *udev, uint8_t index) 199{ 200 int rc; 201 uint16_t val; 202 203 /* issue the PHY read request and wait for its execution */ 204 rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_READ, index); 205 if (rc < 0) 206 return rc; 207 208 /* fetch the PHY data which was read */ 209 rc = mcs7830_read_reg(udev, REG_PHY_DATA, sizeof(val), &val); 210 if (rc < 0) 211 return rc; 212 rc = le16_to_cpu(val); 213 debug("%s(%d) => 0x%04X\n", __func__, index, rc); 214 return rc; 215} 216 217/* 218 * mcs7830_write_phy() - write a PHY register of the network adapter 219 * @udev: network device to write to 220 * @index: index of the PHY register to write to 221 * @val: value to write to the PHY register 222 * Return: zero upon success, negative upon error 223 */ 224static int mcs7830_write_phy(struct usb_device *udev, uint8_t index, 225 uint16_t val) 226{ 227 int rc; 228 229 debug("%s(%d, 0x%04X)\n", __func__, index, val); 230 231 /* setup the PHY data which is to get written */ 232 val = cpu_to_le16(val); 233 rc = mcs7830_write_reg(udev, REG_PHY_DATA, sizeof(val), &val); 234 if (rc < 0) 235 return rc; 236 237 /* issue the PHY write request and wait for its execution */ 238 rc = mcs7830_phy_emit_wait(udev, PHY_CMD1_WRITE, index); 239 if (rc < 0) 240 return rc; 241 242 return 0; 243} 244 245/* 246 * mcs7830_write_config() - write to the network adapter's config register 247 * @udev: network device to write to 248 * @priv: private data 249 * Return: zero upon success, negative upon error 250 * 251 * the data which gets written is taken from the shadow config register 252 * within the device driver's private data 253 */ 254static int mcs7830_write_config(struct usb_device *udev, 255 struct mcs7830_private *priv) 256{ 257 int rc; 258 259 debug("%s()\n", __func__); 260 261 rc = mcs7830_write_reg(udev, REG_CONFIG, 262 sizeof(priv->config), &priv->config); 263 if (rc < 0) { 264 debug("writing config to adapter failed\n"); 265 return rc; 266 } 267 268 return 0; 269} 270 271/* 272 * mcs7830_write_mchash() - write the network adapter's multicast filter 273 * @udev: network device to write to 274 * @priv: private data 275 * Return: zero upon success, negative upon error 276 * 277 * the data which gets written is taken from the shadow multicast hashes 278 * within the device driver's private data 279 */ 280static int mcs7830_write_mchash(struct usb_device *udev, 281 struct mcs7830_private *priv) 282{ 283 int rc; 284 285 debug("%s()\n", __func__); 286 287 rc = mcs7830_write_reg(udev, REG_MULTICAST_HASH, 288 sizeof(priv->mchash), &priv->mchash); 289 if (rc < 0) { 290 debug("writing multicast hash to adapter failed\n"); 291 return rc; 292 } 293 294 return 0; 295} 296 297/* 298 * mcs7830_set_autoneg() - setup and trigger ethernet link autonegotiation 299 * @udev: network device to run link negotiation on 300 * Return: zero upon success, negative upon error 301 * 302 * the routine advertises available media and starts autonegotiation 303 */ 304static int mcs7830_set_autoneg(struct usb_device *udev) 305{ 306 int adv, flg; 307 int rc; 308 309 debug("%s()\n", __func__); 310 311 /* 312 * algorithm taken from the Linux driver, which took it from 313 * "the original mcs7830 version 1.4 driver": 314 * 315 * enable all media, reset BMCR, enable auto neg, restart 316 * auto neg while keeping the enable auto neg flag set 317 */ 318 319 adv = ADVERTISE_PAUSE_CAP | ADVERTISE_ALL | ADVERTISE_CSMA; 320 rc = mcs7830_write_phy(udev, MII_ADVERTISE, adv); 321 322 flg = 0; 323 if (!rc) 324 rc = mcs7830_write_phy(udev, MII_BMCR, flg); 325 326 flg |= BMCR_ANENABLE; 327 if (!rc) 328 rc = mcs7830_write_phy(udev, MII_BMCR, flg); 329 330 flg |= BMCR_ANRESTART; 331 if (!rc) 332 rc = mcs7830_write_phy(udev, MII_BMCR, flg); 333 334 return rc; 335} 336 337/* 338 * mcs7830_get_rev() - identify a network adapter's chip revision 339 * @udev: network device to identify 340 * Return: non-negative number, reflecting the revision number 341 * 342 * currently, only "rev C and higher" and "below rev C" are needed, so 343 * the return value is #1 for "below rev C", and #2 for "rev C and above" 344 */ 345static int mcs7830_get_rev(struct usb_device *udev) 346{ 347 uint8_t buf[2]; 348 int rc; 349 int rev; 350 351 /* register 22 is readable in rev C and higher */ 352 rc = mcs7830_read_reg(udev, REG_FRAME_DROP_COUNTER, sizeof(buf), buf); 353 if (rc < 0) 354 rev = 1; 355 else 356 rev = 2; 357 debug("%s() rc=%d, rev=%d\n", __func__, rc, rev); 358 return rev; 359} 360 361/* 362 * mcs7830_apply_fixup() - identify an adapter and potentially apply fixups 363 * @udev: network device to identify and apply fixups to 364 * Return: zero upon success (no errors emitted from here) 365 * 366 * this routine identifies the network adapter's chip revision, and applies 367 * fixups for known issues 368 */ 369static int mcs7830_apply_fixup(struct usb_device *udev) 370{ 371 int rev; 372 int i; 373 uint8_t thr; 374 375 rev = mcs7830_get_rev(udev); 376 debug("%s() rev=%d\n", __func__, rev); 377 378 /* 379 * rev C requires setting the pause threshold (the Linux driver 380 * is inconsistent, the implementation does it for "rev C 381 * exactly", the introductory comment says "rev C and above") 382 */ 383 if (rev == 2) { 384 debug("%s: applying rev C fixup\n", __func__); 385 thr = PAUSE_THRESHOLD_DEFAULT; 386 for (i = 0; i < 2; i++) { 387 (void)mcs7830_write_reg(udev, REG_PAUSE_THRESHOLD, 388 sizeof(thr), &thr); 389 mdelay(1); 390 } 391 } 392 393 return 0; 394} 395 396/* 397 * mcs7830_basic_reset() - bring the network adapter into a known first state 398 * @eth: network device to act upon 399 * Return: zero upon success, negative upon error 400 * 401 * this routine initializes the network adapter such that subsequent invocations 402 * of the interface callbacks can exchange ethernet frames; link negotiation is 403 * triggered from here already and continues in background 404 */ 405static int mcs7830_basic_reset(struct usb_device *udev, 406 struct mcs7830_private *priv) 407{ 408 int rc; 409 410 debug("%s()\n", __func__); 411 412 /* 413 * comment from the respective Linux driver, which 414 * unconditionally sets the ALLMULTICAST flag as well: 415 * should not be needed, but does not work otherwise 416 */ 417 priv->config = CONF_TXENABLE; 418 priv->config |= CONF_ALLMULTICAST; 419 420 rc = mcs7830_set_autoneg(udev); 421 if (rc < 0) { 422 pr_err("setting autoneg failed\n"); 423 return rc; 424 } 425 426 rc = mcs7830_write_mchash(udev, priv); 427 if (rc < 0) { 428 pr_err("failed to set multicast hash\n"); 429 return rc; 430 } 431 432 rc = mcs7830_write_config(udev, priv); 433 if (rc < 0) { 434 pr_err("failed to set configuration\n"); 435 return rc; 436 } 437 438 rc = mcs7830_apply_fixup(udev); 439 if (rc < 0) { 440 pr_err("fixup application failed\n"); 441 return rc; 442 } 443 444 return 0; 445} 446 447/* 448 * mcs7830_read_mac() - read an ethernet adapter's MAC address 449 * @udev: network device to read from 450 * @enetaddr: place to put ethernet MAC address 451 * Return: zero upon success, negative upon error 452 * 453 * this routine fetches the MAC address stored within the ethernet adapter, 454 * and stores it in the ethernet interface's data structure 455 */ 456static int mcs7830_read_mac(struct usb_device *udev, unsigned char enetaddr[]) 457{ 458 int rc; 459 uint8_t buf[ETH_ALEN]; 460 461 debug("%s()\n", __func__); 462 463 rc = mcs7830_read_reg(udev, REG_ETHER_ADDR, ETH_ALEN, buf); 464 if (rc < 0) { 465 debug("reading MAC from adapter failed\n"); 466 return rc; 467 } 468 469 memcpy(enetaddr, buf, ETH_ALEN); 470 return 0; 471} 472 473static int mcs7830_write_mac_common(struct usb_device *udev, 474 unsigned char enetaddr[]) 475{ 476 int rc; 477 478 debug("%s()\n", __func__); 479 480 rc = mcs7830_write_reg(udev, REG_ETHER_ADDR, ETH_ALEN, enetaddr); 481 if (rc < 0) { 482 debug("writing MAC to adapter failed\n"); 483 return rc; 484 } 485 return 0; 486} 487 488static int mcs7830_init_common(struct usb_device *udev) 489{ 490 int timeout; 491 int have_link; 492 493 debug("%s()\n", __func__); 494 495 timeout = 0; 496 do { 497 have_link = mcs7830_read_phy(udev, MII_BMSR) & BMSR_LSTATUS; 498 if (have_link) 499 break; 500 udelay(LINKSTATUS_TIMEOUT_RES * 1000); 501 timeout += LINKSTATUS_TIMEOUT_RES; 502 } while (timeout < LINKSTATUS_TIMEOUT); 503 if (!have_link) { 504 debug("ethernet link is down\n"); 505 return -ETIMEDOUT; 506 } 507 return 0; 508} 509 510static int mcs7830_send_common(struct ueth_data *ueth, void *packet, 511 int length) 512{ 513 struct usb_device *udev = ueth->pusb_dev; 514 int rc; 515 int gotlen; 516 /* there is a status byte after the ethernet frame */ 517 ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, PKTSIZE + sizeof(uint8_t)); 518 519 memcpy(buf, packet, length); 520 rc = usb_bulk_msg(udev, 521 usb_sndbulkpipe(udev, ueth->ep_out), 522 &buf[0], length, &gotlen, 523 USBCALL_TIMEOUT); 524 debug("%s() TX want len %d, got len %d, rc %d\n", 525 __func__, length, gotlen, rc); 526 return rc; 527} 528 529static int mcs7830_recv_common(struct ueth_data *ueth, uint8_t *buf) 530{ 531 int rc, wantlen, gotlen; 532 uint8_t sts; 533 534 debug("%s()\n", __func__); 535 536 /* fetch input data from the adapter */ 537 wantlen = MCS7830_RX_URB_SIZE; 538 rc = usb_bulk_msg(ueth->pusb_dev, 539 usb_rcvbulkpipe(ueth->pusb_dev, ueth->ep_in), 540 &buf[0], wantlen, &gotlen, 541 USBCALL_TIMEOUT); 542 debug("%s() RX want len %d, got len %d, rc %d\n", 543 __func__, wantlen, gotlen, rc); 544 if (rc != 0) { 545 pr_err("RX: failed to receive\n"); 546 return rc; 547 } 548 if (gotlen > wantlen) { 549 pr_err("RX: got too many bytes (%d)\n", gotlen); 550 return -EIO; 551 } 552 553 /* 554 * the bulk message that we received from USB contains exactly 555 * one ethernet frame and a trailing status byte 556 */ 557 if (gotlen < sizeof(sts)) 558 return -EIO; 559 gotlen -= sizeof(sts); 560 sts = buf[gotlen]; 561 562 if (sts == STAT_RX_FRAME_CORRECT) { 563 debug("%s() got a frame, len=%d\n", __func__, gotlen); 564 return gotlen; 565 } 566 567 debug("RX: frame error (sts 0x%02X, %s %s %s %s %s)\n", 568 sts, 569 (sts & STAT_RX_LARGE_FRAME) ? "large" : "-", 570 (sts & STAT_RX_LENGTH_ERROR) ? "length" : "-", 571 (sts & STAT_RX_SHORT_FRAME) ? "short" : "-", 572 (sts & STAT_RX_CRC_ERROR) ? "crc" : "-", 573 (sts & STAT_RX_ALIGNMENT_ERROR) ? "align" : "-"); 574 return -EIO; 575} 576 577static int mcs7830_eth_start(struct udevice *dev) 578{ 579 struct usb_device *udev = dev_get_parent_priv(dev); 580 581 return mcs7830_init_common(udev); 582} 583 584void mcs7830_eth_stop(struct udevice *dev) 585{ 586 debug("** %s()\n", __func__); 587} 588 589int mcs7830_eth_send(struct udevice *dev, void *packet, int length) 590{ 591 struct mcs7830_private *priv = dev_get_priv(dev); 592 struct ueth_data *ueth = &priv->ueth; 593 594 return mcs7830_send_common(ueth, packet, length); 595} 596 597int mcs7830_eth_recv(struct udevice *dev, int flags, uchar **packetp) 598{ 599 struct mcs7830_private *priv = dev_get_priv(dev); 600 struct ueth_data *ueth = &priv->ueth; 601 int len; 602 603 len = mcs7830_recv_common(ueth, priv->rx_buf); 604 *packetp = priv->rx_buf; 605 606 return len; 607} 608 609static int mcs7830_free_pkt(struct udevice *dev, uchar *packet, int packet_len) 610{ 611 struct mcs7830_private *priv = dev_get_priv(dev); 612 613 packet_len = ALIGN(packet_len, 4); 614 usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len); 615 616 return 0; 617} 618 619int mcs7830_write_hwaddr(struct udevice *dev) 620{ 621 struct usb_device *udev = dev_get_parent_priv(dev); 622 struct eth_pdata *pdata = dev_get_plat(dev); 623 624 return mcs7830_write_mac_common(udev, pdata->enetaddr); 625} 626 627static int mcs7830_eth_probe(struct udevice *dev) 628{ 629 struct usb_device *udev = dev_get_parent_priv(dev); 630 struct mcs7830_private *priv = dev_get_priv(dev); 631 struct eth_pdata *pdata = dev_get_plat(dev); 632 struct ueth_data *ueth = &priv->ueth; 633 634 if (mcs7830_basic_reset(udev, priv)) 635 return 0; 636 637 if (mcs7830_read_mac(udev, pdata->enetaddr)) 638 return 0; 639 640 return usb_ether_register(dev, ueth, MCS7830_RX_URB_SIZE); 641} 642 643static const struct eth_ops mcs7830_eth_ops = { 644 .start = mcs7830_eth_start, 645 .send = mcs7830_eth_send, 646 .recv = mcs7830_eth_recv, 647 .free_pkt = mcs7830_free_pkt, 648 .stop = mcs7830_eth_stop, 649 .write_hwaddr = mcs7830_write_hwaddr, 650}; 651 652U_BOOT_DRIVER(mcs7830_eth) = { 653 .name = "mcs7830_eth", 654 .id = UCLASS_ETH, 655 .probe = mcs7830_eth_probe, 656 .ops = &mcs7830_eth_ops, 657 .priv_auto = sizeof(struct mcs7830_private), 658 .plat_auto = sizeof(struct eth_pdata), 659 .flags = DM_FLAG_ALLOC_PRIV_DMA, 660}; 661 662static const struct usb_device_id mcs7830_eth_id_table[] = { 663 { USB_DEVICE(0x9710, 0x7832) }, /* Moschip 7832 */ 664 { USB_DEVICE(0x9710, 0x7830), }, /* Moschip 7830 */ 665 { USB_DEVICE(0x9710, 0x7730), }, /* Moschip 7730 */ 666 { USB_DEVICE(0x0df6, 0x0021), }, /* Sitecom LN 30 */ 667 { } /* Terminating entry */ 668}; 669 670U_BOOT_USB_DEVICE(mcs7830_eth, mcs7830_eth_id_table); 671