uboot/drivers/usb/eth/lan7x.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2017 Microchip Technology Inc. All rights reserved.
   3 *
   4 * SPDX-License-Identifier:     GPL-2.0+
   5 */
   6
   7#include <dm.h>
   8#include <malloc.h>
   9#include <miiphy.h>
  10#include <memalign.h>
  11#include <usb.h>
  12#include <linux/ethtool.h>
  13#include <linux/mii.h>
  14#include "usb_ether.h"
  15#include "lan7x.h"
  16
  17/*
  18 * Lan7x infrastructure commands
  19 */
  20int lan7x_write_reg(struct usb_device *udev, u32 index, u32 data)
  21{
  22        int len;
  23        ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
  24
  25        cpu_to_le32s(&data);
  26        tmpbuf[0] = data;
  27
  28        len = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
  29                              USB_VENDOR_REQUEST_WRITE_REGISTER,
  30                              USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  31                              0, index, tmpbuf, sizeof(data),
  32                              USB_CTRL_SET_TIMEOUT_MS);
  33        if (len != sizeof(data)) {
  34                debug("%s failed: index=%d, data=%d, len=%d",
  35                      __func__, index, data, len);
  36                return -EIO;
  37        }
  38        return 0;
  39}
  40
  41int lan7x_read_reg(struct usb_device *udev, u32 index, u32 *data)
  42{
  43        int len;
  44        ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
  45
  46        len = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
  47                              USB_VENDOR_REQUEST_READ_REGISTER,
  48                              USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
  49                              0, index, tmpbuf, sizeof(*data),
  50                              USB_CTRL_GET_TIMEOUT_MS);
  51        *data = tmpbuf[0];
  52        if (len != sizeof(*data)) {
  53                debug("%s failed: index=%d, len=%d", __func__, index, len);
  54                return -EIO;
  55        }
  56
  57        le32_to_cpus(data);
  58        return 0;
  59}
  60
  61static int lan7x_phy_wait_not_busy(struct usb_device *udev)
  62{
  63        return lan7x_wait_for_bit(udev, __func__,
  64                                  MII_ACC, MII_ACC_MII_BUSY,
  65                                  false, 100, 0);
  66}
  67
  68int lan7x_mdio_read(struct usb_device *udev, int phy_id, int idx)
  69{
  70        u32 val, addr;
  71
  72        /* confirm MII not busy */
  73        if (lan7x_phy_wait_not_busy(udev)) {
  74                debug("MII is busy in %s\n", __func__);
  75                return -ETIMEDOUT;
  76        }
  77
  78        /* set the address, index & direction (read from PHY) */
  79        addr = (phy_id << 11) | (idx << 6) |
  80                MII_ACC_MII_READ | MII_ACC_MII_BUSY;
  81        lan7x_write_reg(udev, MII_ACC, addr);
  82
  83        if (lan7x_phy_wait_not_busy(udev)) {
  84                debug("Timed out reading MII reg %02X\n", idx);
  85                return -ETIMEDOUT;
  86        }
  87
  88        lan7x_read_reg(udev, MII_DATA, &val);
  89
  90        return val & 0xFFFF;
  91}
  92
  93void lan7x_mdio_write(struct usb_device *udev, int phy_id, int idx, int regval)
  94{
  95        u32 addr;
  96
  97        /* confirm MII not busy */
  98        if (lan7x_phy_wait_not_busy(udev)) {
  99                debug("MII is busy in %s\n", __func__);
 100                return;
 101        }
 102
 103        lan7x_write_reg(udev, MII_DATA, regval);
 104
 105        /* set the address, index & direction (write to PHY) */
 106        addr = (phy_id << 11) | (idx << 6) |
 107                MII_ACC_MII_WRITE | MII_ACC_MII_BUSY;
 108        lan7x_write_reg(udev, MII_ACC, addr);
 109
 110        if (lan7x_phy_wait_not_busy(udev))
 111                debug("Timed out writing MII reg %02X\n", idx);
 112}
 113
 114/*
 115 * Lan7x phylib wrappers
 116 */
 117static int lan7x_phylib_mdio_read(struct mii_dev *bus,
 118                                  int addr, int devad, int reg)
 119{
 120        struct usb_device *udev = dev_get_parent_priv(bus->priv);
 121
 122        return lan7x_mdio_read(udev, addr, reg);
 123}
 124
 125static int lan7x_phylib_mdio_write(struct mii_dev *bus,
 126                                   int addr, int devad, int reg, u16 val)
 127{
 128        struct usb_device *udev = dev_get_parent_priv(bus->priv);
 129
 130        lan7x_mdio_write(udev, addr, reg, (int)val);
 131
 132        return 0;
 133}
 134
 135/*
 136 * Lan7x eeprom functions
 137 */
 138static int lan7x_eeprom_confirm_not_busy(struct usb_device *udev)
 139{
 140        return lan7x_wait_for_bit(udev, __func__,
 141                                  E2P_CMD, E2P_CMD_EPC_BUSY,
 142                                  false, 100, 0);
 143}
 144
 145static int lan7x_wait_eeprom(struct usb_device *udev)
 146{
 147        return lan7x_wait_for_bit(udev, __func__,
 148                                  E2P_CMD,
 149                                  (E2P_CMD_EPC_BUSY | E2P_CMD_EPC_TIMEOUT),
 150                                  false, 100, 0);
 151}
 152
 153static int lan7x_read_eeprom(struct usb_device *udev,
 154                             u32 offset, u32 length, u8 *data)
 155{
 156        u32 val;
 157        int i, ret;
 158
 159        ret = lan7x_eeprom_confirm_not_busy(udev);
 160        if (ret)
 161                return ret;
 162
 163        for (i = 0; i < length; i++) {
 164                val = E2P_CMD_EPC_BUSY | E2P_CMD_EPC_CMD_READ |
 165                        (offset & E2P_CMD_EPC_ADDR_MASK);
 166                lan7x_write_reg(udev, E2P_CMD, val);
 167
 168                ret = lan7x_wait_eeprom(udev);
 169                if (ret)
 170                        return ret;
 171
 172                lan7x_read_reg(udev, E2P_DATA, &val);
 173                data[i] = val & 0xFF;
 174                offset++;
 175        }
 176        return ret;
 177}
 178
 179/*
 180 * Lan7x phylib functions
 181 */
 182int lan7x_phylib_register(struct udevice *udev)
 183{
 184        struct usb_device *usbdev = dev_get_parent_priv(udev);
 185        struct lan7x_private *priv = dev_get_priv(udev);
 186        int ret;
 187
 188        priv->mdiobus = mdio_alloc();
 189        if (!priv->mdiobus) {
 190                printf("mdio_alloc failed\n");
 191                return -ENOMEM;
 192        }
 193        priv->mdiobus->read = lan7x_phylib_mdio_read;
 194        priv->mdiobus->write = lan7x_phylib_mdio_write;
 195        sprintf(priv->mdiobus->name,
 196                "lan7x_mdiobus-d%hu-p%hu", usbdev->devnum, usbdev->portnr);
 197        priv->mdiobus->priv = (void *)udev;
 198
 199        ret = mdio_register(priv->mdiobus);
 200        if (ret) {
 201                printf("mdio_register failed\n");
 202                free(priv->mdiobus);
 203                return -ENOMEM;
 204        }
 205
 206        return 0;
 207}
 208
 209int lan7x_eth_phylib_connect(struct udevice *udev, struct ueth_data *dev)
 210{
 211        struct lan7x_private *priv = dev_get_priv(udev);
 212
 213        priv->phydev = phy_connect(priv->mdiobus, dev->phy_id,
 214                             udev, PHY_INTERFACE_MODE_MII);
 215
 216        if (!priv->phydev) {
 217                printf("phy_connect failed\n");
 218                return -ENODEV;
 219        }
 220        return 0;
 221}
 222
 223int lan7x_eth_phylib_config_start(struct udevice *udev)
 224{
 225        struct lan7x_private *priv = dev_get_priv(udev);
 226        int ret;
 227
 228        /* configure supported modes */
 229        priv->phydev->supported = PHY_BASIC_FEATURES |
 230                                  SUPPORTED_1000baseT_Full |
 231                                  SUPPORTED_Pause |
 232                                  SUPPORTED_Asym_Pause;
 233
 234        priv->phydev->advertising = ADVERTISED_10baseT_Half |
 235                                    ADVERTISED_10baseT_Full |
 236                                    ADVERTISED_100baseT_Half |
 237                                    ADVERTISED_100baseT_Full |
 238                                    ADVERTISED_1000baseT_Full |
 239                                    ADVERTISED_Pause |
 240                                    ADVERTISED_Asym_Pause |
 241                                    ADVERTISED_Autoneg;
 242
 243        priv->phydev->autoneg = AUTONEG_ENABLE;
 244
 245        ret = genphy_config_aneg(priv->phydev);
 246        if (ret) {
 247                printf("genphy_config_aneg failed\n");
 248                return ret;
 249        }
 250        ret = phy_startup(priv->phydev);
 251        if (ret) {
 252                printf("phy_startup failed\n");
 253                return ret;
 254        }
 255
 256        debug("** %s() speed %i duplex %i adv %X supp %X\n", __func__,
 257              priv->phydev->speed, priv->phydev->duplex,
 258              priv->phydev->advertising, priv->phydev->supported);
 259
 260        return 0;
 261}
 262
 263int lan7x_update_flowcontrol(struct usb_device *udev,
 264                             struct ueth_data *dev,
 265                             uint32_t *flow, uint32_t *fct_flow)
 266{
 267        uint32_t lcladv, rmtadv;
 268        u8 cap = 0;
 269        struct lan7x_private *priv = dev_get_priv(udev->dev);
 270
 271        debug("** %s()\n", __func__);
 272        debug("** %s() priv->phydev->speed %i duplex %i\n", __func__,
 273              priv->phydev->speed, priv->phydev->duplex);
 274
 275        if (priv->phydev->duplex == DUPLEX_FULL) {
 276                lcladv = lan7x_mdio_read(udev, dev->phy_id, MII_ADVERTISE);
 277                rmtadv = lan7x_mdio_read(udev, dev->phy_id, MII_LPA);
 278                cap = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
 279
 280                debug("TX Flow ");
 281                if (cap & FLOW_CTRL_TX) {
 282                        *flow = (FLOW_CR_TX_FCEN | 0xFFFF);
 283                        /* set fct_flow thresholds to 20% and 80% */
 284                        *fct_flow = ((MAX_RX_FIFO_SIZE * 2) / (10 * 512))
 285                                        & 0x7FUL;
 286                        *fct_flow <<= 8UL;
 287                        *fct_flow |= ((MAX_RX_FIFO_SIZE * 8) / (10 * 512))
 288                                        & 0x7FUL;
 289                        debug("EN ");
 290                } else {
 291                        debug("DIS ");
 292                }
 293                debug("RX Flow ");
 294                if (cap & FLOW_CTRL_RX) {
 295                        *flow |= FLOW_CR_RX_FCEN;
 296                        debug("EN");
 297                } else {
 298                        debug("DIS");
 299                }
 300        }
 301        debug("\n");
 302        return 0;
 303}
 304
 305int lan7x_read_eeprom_mac(unsigned char *enetaddr, struct usb_device *udev)
 306{
 307        int ret;
 308
 309        memset(enetaddr, 0, 6);
 310
 311        ret = lan7x_read_eeprom(udev, 0, 1, enetaddr);
 312
 313        if ((ret == 0) && (enetaddr[0] == EEPROM_INDICATOR)) {
 314                ret = lan7x_read_eeprom(udev,
 315                                        EEPROM_MAC_OFFSET, ETH_ALEN,
 316                                        enetaddr);
 317                if ((ret == 0) && is_valid_ethaddr(enetaddr)) {
 318                        /* eeprom values are valid so use them */
 319                        debug("MAC address read from EEPROM %pM\n",
 320                              enetaddr);
 321                        return 0;
 322                }
 323        }
 324        debug("MAC address read from EEPROM invalid %pM\n", enetaddr);
 325
 326        memset(enetaddr, 0, 6);
 327        return -EINVAL;
 328}
 329
 330int lan7x_pmt_phy_reset(struct usb_device *udev,
 331                        struct ueth_data *dev)
 332{
 333        int ret;
 334        u32 data;
 335
 336        ret = lan7x_read_reg(udev, PMT_CTL, &data);
 337        if (ret)
 338                return ret;
 339        ret = lan7x_write_reg(udev, PMT_CTL, data | PMT_CTL_PHY_RST);
 340        if (ret)
 341                return ret;
 342
 343        /* for LAN7x, we need to check PMT_CTL_READY asserted */
 344        ret = lan7x_wait_for_bit(udev, "PMT_CTL_PHY_RST",
 345                                 PMT_CTL, PMT_CTL_PHY_RST,
 346                                 false, 1000, 0); /* could take over 125mS */
 347        if (ret)
 348                return ret;
 349
 350        return lan7x_wait_for_bit(udev, "PMT_CTL_READY",
 351                                 PMT_CTL, PMT_CTL_READY,
 352                                 true, 1000, 0);
 353}
 354
 355int lan7x_basic_reset(struct usb_device *udev,
 356                      struct ueth_data *dev)
 357{
 358        int ret;
 359
 360        dev->phy_id = LAN7X_INTERNAL_PHY_ID; /* fixed phy id */
 361
 362        ret = lan7x_write_reg(udev, HW_CFG, HW_CFG_LRST);
 363        if (ret)
 364                return ret;
 365
 366        ret = lan7x_wait_for_bit(udev, "HW_CFG_LRST",
 367                                 HW_CFG, HW_CFG_LRST,
 368                                 false, 1000, 0);
 369        if (ret)
 370                return ret;
 371
 372        debug("USB devnum %d portnr %d\n", udev->devnum, udev->portnr);
 373
 374        return lan7x_pmt_phy_reset(udev, dev);
 375}
 376
 377void lan7x_eth_stop(struct udevice *dev)
 378{
 379        debug("** %s()\n", __func__);
 380}
 381
 382int lan7x_eth_send(struct udevice *dev, void *packet, int length)
 383{
 384        struct lan7x_private *priv = dev_get_priv(dev);
 385        struct ueth_data *ueth = &priv->ueth;
 386        int err;
 387        int actual_len;
 388        u32 tx_cmd_a;
 389        u32 tx_cmd_b;
 390        ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
 391                                 PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
 392
 393        debug("** %s(), len %d, buf %#x\n", __func__, length,
 394              (unsigned int)(ulong) msg);
 395        if (length > PKTSIZE)
 396                return -ENOSPC;
 397
 398        /* LAN7x disable all TX offload features for u-boot */
 399        tx_cmd_a = (u32) (length & TX_CMD_A_LEN_MASK) | TX_CMD_A_FCS;
 400        tx_cmd_b = 0;
 401        cpu_to_le32s(&tx_cmd_a);
 402        cpu_to_le32s(&tx_cmd_b);
 403
 404        /* prepend cmd_a and cmd_b */
 405        memcpy(msg, &tx_cmd_a, sizeof(tx_cmd_a));
 406        memcpy(msg + sizeof(tx_cmd_a), &tx_cmd_b, sizeof(tx_cmd_b));
 407        memcpy(msg + sizeof(tx_cmd_a) + sizeof(tx_cmd_b), (void *)packet,
 408               length);
 409        err = usb_bulk_msg(ueth->pusb_dev,
 410                           usb_sndbulkpipe(ueth->pusb_dev, ueth->ep_out),
 411                           (void *)msg,
 412                           length + sizeof(tx_cmd_a) +
 413                           sizeof(tx_cmd_b),
 414                           &actual_len, USB_BULK_SEND_TIMEOUT_MS);
 415        debug("Tx: len = %u, actual = %u, err = %d\n",
 416              (unsigned int)(length + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)),
 417              (unsigned int)actual_len, err);
 418
 419        return err;
 420}
 421
 422int lan7x_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 423{
 424        struct lan7x_private *priv = dev_get_priv(dev);
 425        struct ueth_data *ueth = &priv->ueth;
 426        uint8_t *ptr;
 427        int ret, len;
 428        u32 packet_len = 0;
 429        u32 rx_cmd_a = 0;
 430
 431        len = usb_ether_get_rx_bytes(ueth, &ptr);
 432        debug("%s: first try, len=%d\n", __func__, len);
 433        if (!len) {
 434                if (!(flags & ETH_RECV_CHECK_DEVICE))
 435                        return -EAGAIN;
 436                ret = usb_ether_receive(ueth, RX_URB_SIZE);
 437                if (ret == -EAGAIN)
 438                        return ret;
 439
 440                len = usb_ether_get_rx_bytes(ueth, &ptr);
 441                debug("%s: second try, len=%d\n", __func__, len);
 442        }
 443
 444        /*
 445         * 1st 4 bytes contain the length of the actual data plus error info.
 446         * Extract data length.
 447         */
 448        if (len < sizeof(packet_len)) {
 449                debug("Rx: incomplete packet length\n");
 450                goto err;
 451        }
 452        memcpy(&rx_cmd_a, ptr, sizeof(rx_cmd_a));
 453        le32_to_cpus(&rx_cmd_a);
 454        if (rx_cmd_a & RX_CMD_A_RXE) {
 455                debug("Rx: Error header=%#x", rx_cmd_a);
 456                goto err;
 457        }
 458        packet_len = (u16) (rx_cmd_a & RX_CMD_A_LEN_MASK);
 459
 460        if (packet_len > len - sizeof(packet_len)) {
 461                debug("Rx: too large packet: %d\n", packet_len);
 462                goto err;
 463        }
 464
 465        /*
 466         * For LAN7x, the length in command A does not
 467         * include command A, B, and C length.
 468         * So use it as is.
 469         */
 470
 471        *packetp = ptr + 10;
 472        return packet_len;
 473
 474err:
 475        usb_ether_advance_rxbuf(ueth, -1);
 476        return -EINVAL;
 477}
 478
 479int lan7x_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
 480{
 481        struct lan7x_private *priv = dev_get_priv(dev);
 482
 483        packet_len = ALIGN(packet_len, 4);
 484        usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
 485
 486        return 0;
 487}
 488
 489int lan7x_eth_remove(struct udevice *dev)
 490{
 491        struct lan7x_private *priv = dev_get_priv(dev);
 492
 493        debug("** %s()\n", __func__);
 494        free(priv->phydev);
 495        mdio_unregister(priv->mdiobus);
 496        mdio_free(priv->mdiobus);
 497
 498        return 0;
 499}
 500