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