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