uboot/drivers/net/bcm6368-eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018 Álvaro Fernández Rojas <noltari@gmail.com>
   4 *
   5 * Derived from linux/drivers/net/ethernet/broadcom/bcm63xx_enet.c:
   6 *      Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
   7 */
   8
   9#include <common.h>
  10#include <clk.h>
  11#include <dm.h>
  12#include <dma.h>
  13#include <log.h>
  14#include <malloc.h>
  15#include <miiphy.h>
  16#include <net.h>
  17#include <reset.h>
  18#include <wait_bit.h>
  19#include <asm/io.h>
  20#include <dm/device_compat.h>
  21#include <linux/delay.h>
  22
  23#define ETH_PORT_STR                    "brcm,enetsw-port"
  24
  25#define ETH_RX_DESC                     PKTBUFSRX
  26#define ETH_ZLEN                        60
  27#define ETH_TIMEOUT                     100
  28
  29#define ETH_MAX_PORT                    8
  30#define ETH_RGMII_PORT0                 4
  31
  32/* Port traffic control */
  33#define ETH_PTCTRL_REG(x)               (0x0 + (x))
  34#define ETH_PTCTRL_RXDIS_SHIFT          0
  35#define ETH_PTCTRL_RXDIS_MASK           (1 << ETH_PTCTRL_RXDIS_SHIFT)
  36#define ETH_PTCTRL_TXDIS_SHIFT          1
  37#define ETH_PTCTRL_TXDIS_MASK           (1 << ETH_PTCTRL_TXDIS_SHIFT)
  38
  39/* Switch mode register */
  40#define ETH_SWMODE_REG                  0xb
  41#define ETH_SWMODE_FWD_EN_SHIFT         1
  42#define ETH_SWMODE_FWD_EN_MASK          (1 << ETH_SWMODE_FWD_EN_SHIFT)
  43
  44/* IMP override Register */
  45#define ETH_IMPOV_REG                   0xe
  46#define ETH_IMPOV_LINKUP_SHIFT          0
  47#define ETH_IMPOV_LINKUP_MASK           (1 << ETH_IMPOV_LINKUP_SHIFT)
  48#define ETH_IMPOV_FDX_SHIFT             1
  49#define ETH_IMPOV_FDX_MASK              (1 << ETH_IMPOV_FDX_SHIFT)
  50#define ETH_IMPOV_100_SHIFT             2
  51#define ETH_IMPOV_100_MASK              (1 << ETH_IMPOV_100_SHIFT)
  52#define ETH_IMPOV_1000_SHIFT            3
  53#define ETH_IMPOV_1000_MASK             (1 << ETH_IMPOV_1000_SHIFT)
  54#define ETH_IMPOV_RXFLOW_SHIFT          4
  55#define ETH_IMPOV_RXFLOW_MASK           (1 << ETH_IMPOV_RXFLOW_SHIFT)
  56#define ETH_IMPOV_TXFLOW_SHIFT          5
  57#define ETH_IMPOV_TXFLOW_MASK           (1 << ETH_IMPOV_TXFLOW_SHIFT)
  58#define ETH_IMPOV_FORCE_SHIFT           7
  59#define ETH_IMPOV_FORCE_MASK            (1 << ETH_IMPOV_FORCE_SHIFT)
  60
  61/* Port override Register */
  62#define ETH_PORTOV_REG(x)               (0x58 + (x))
  63#define ETH_PORTOV_LINKUP_SHIFT         0
  64#define ETH_PORTOV_LINKUP_MASK          (1 << ETH_PORTOV_LINKUP_SHIFT)
  65#define ETH_PORTOV_FDX_SHIFT            1
  66#define ETH_PORTOV_FDX_MASK             (1 << ETH_PORTOV_FDX_SHIFT)
  67#define ETH_PORTOV_100_SHIFT            2
  68#define ETH_PORTOV_100_MASK             (1 << ETH_PORTOV_100_SHIFT)
  69#define ETH_PORTOV_1000_SHIFT           3
  70#define ETH_PORTOV_1000_MASK            (1 << ETH_PORTOV_1000_SHIFT)
  71#define ETH_PORTOV_RXFLOW_SHIFT         4
  72#define ETH_PORTOV_RXFLOW_MASK          (1 << ETH_PORTOV_RXFLOW_SHIFT)
  73#define ETH_PORTOV_TXFLOW_SHIFT         5
  74#define ETH_PORTOV_TXFLOW_MASK          (1 << ETH_PORTOV_TXFLOW_SHIFT)
  75#define ETH_PORTOV_ENABLE_SHIFT         6
  76#define ETH_PORTOV_ENABLE_MASK          (1 << ETH_PORTOV_ENABLE_SHIFT)
  77
  78/* Port RGMII control register */
  79#define ETH_RGMII_CTRL_REG(x)           (0x60 + (x))
  80#define ETH_RGMII_CTRL_GMII_CLK_EN      (1 << 7)
  81#define ETH_RGMII_CTRL_MII_OVERRIDE_EN  (1 << 6)
  82#define ETH_RGMII_CTRL_MII_MODE_MASK    (3 << 4)
  83#define ETH_RGMII_CTRL_RGMII_MODE       (0 << 4)
  84#define ETH_RGMII_CTRL_MII_MODE         (1 << 4)
  85#define ETH_RGMII_CTRL_RVMII_MODE       (2 << 4)
  86#define ETH_RGMII_CTRL_TIMING_SEL_EN    (1 << 0)
  87
  88/* Port RGMII timing register */
  89#define ENETSW_RGMII_TIMING_REG(x)      (0x68 + (x))
  90
  91/* MDIO control register */
  92#define MII_SC_REG                      0xb0
  93#define MII_SC_EXT_SHIFT                16
  94#define MII_SC_EXT_MASK                 (1 << MII_SC_EXT_SHIFT)
  95#define MII_SC_REG_SHIFT                20
  96#define MII_SC_PHYID_SHIFT              25
  97#define MII_SC_RD_SHIFT                 30
  98#define MII_SC_RD_MASK                  (1 << MII_SC_RD_SHIFT)
  99#define MII_SC_WR_SHIFT                 31
 100#define MII_SC_WR_MASK                  (1 << MII_SC_WR_SHIFT)
 101
 102/* MDIO data register */
 103#define MII_DAT_REG                     0xb4
 104
 105/* Global Management Configuration Register */
 106#define ETH_GMCR_REG                    0x200
 107#define ETH_GMCR_RST_MIB_SHIFT          0
 108#define ETH_GMCR_RST_MIB_MASK           (1 << ETH_GMCR_RST_MIB_SHIFT)
 109
 110/* Jumbo control register port mask register */
 111#define ETH_JMBCTL_PORT_REG             0x4004
 112
 113/* Jumbo control mib good frame register */
 114#define ETH_JMBCTL_MAXSIZE_REG          0x4008
 115
 116/* ETH port data */
 117struct bcm_enetsw_port {
 118        bool used;
 119        const char *name;
 120        /* Config */
 121        bool bypass_link;
 122        int force_speed;
 123        bool force_duplex_full;
 124        /* PHY */
 125        int phy_id;
 126};
 127
 128/* ETH data */
 129struct bcm6368_eth_priv {
 130        void __iomem *base;
 131        /* DMA */
 132        struct dma rx_dma;
 133        struct dma tx_dma;
 134        /* Ports */
 135        uint8_t num_ports;
 136        struct bcm_enetsw_port used_ports[ETH_MAX_PORT];
 137        int sw_port_link[ETH_MAX_PORT];
 138        bool rgmii_override;
 139        bool rgmii_timing;
 140        /* PHY */
 141        int phy_id;
 142};
 143
 144static inline bool bcm_enet_port_is_rgmii(int portid)
 145{
 146        return portid >= ETH_RGMII_PORT0;
 147}
 148
 149static int bcm6368_mdio_read(struct bcm6368_eth_priv *priv, uint8_t ext,
 150                             int phy_id, int reg)
 151{
 152        uint32_t val;
 153
 154        writel_be(0, priv->base + MII_SC_REG);
 155
 156        val = MII_SC_RD_MASK |
 157              (phy_id << MII_SC_PHYID_SHIFT) |
 158              (reg << MII_SC_REG_SHIFT);
 159
 160        if (ext)
 161                val |= MII_SC_EXT_MASK;
 162
 163        writel_be(val, priv->base + MII_SC_REG);
 164        udelay(50);
 165
 166        return readw_be(priv->base + MII_DAT_REG);
 167}
 168
 169static int bcm6368_mdio_write(struct bcm6368_eth_priv *priv, uint8_t ext,
 170                              int phy_id, int reg, u16 data)
 171{
 172        uint32_t val;
 173
 174        writel_be(0, priv->base + MII_SC_REG);
 175
 176        val = MII_SC_WR_MASK |
 177              (phy_id << MII_SC_PHYID_SHIFT) |
 178              (reg << MII_SC_REG_SHIFT);
 179
 180        if (ext)
 181                val |= MII_SC_EXT_MASK;
 182
 183        val |= data;
 184
 185        writel_be(val, priv->base + MII_SC_REG);
 186        udelay(50);
 187
 188        return 0;
 189}
 190
 191static int bcm6368_eth_free_pkt(struct udevice *dev, uchar *packet, int len)
 192{
 193        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 194
 195        return dma_prepare_rcv_buf(&priv->rx_dma, packet, len);
 196}
 197
 198static int bcm6368_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 199{
 200        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 201
 202        return dma_receive(&priv->rx_dma, (void**)packetp, NULL);
 203}
 204
 205static int bcm6368_eth_send(struct udevice *dev, void *packet, int length)
 206{
 207        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 208
 209        /* pad packets smaller than ETH_ZLEN */
 210        if (length < ETH_ZLEN) {
 211                memset(packet + length, 0, ETH_ZLEN - length);
 212                length = ETH_ZLEN;
 213        }
 214
 215        return dma_send(&priv->tx_dma, packet, length, NULL);
 216}
 217
 218static int bcm6368_eth_adjust_link(struct udevice *dev)
 219{
 220        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 221        unsigned int i;
 222
 223        for (i = 0; i < priv->num_ports; i++) {
 224                struct bcm_enetsw_port *port;
 225                int val, j, up, adv, lpa, speed, duplex, media;
 226                int external_phy = bcm_enet_port_is_rgmii(i);
 227                u8 override;
 228
 229                port = &priv->used_ports[i];
 230                if (!port->used)
 231                        continue;
 232
 233                if (port->bypass_link)
 234                        continue;
 235
 236                /* dummy read to clear */
 237                for (j = 0; j < 2; j++)
 238                        val = bcm6368_mdio_read(priv, external_phy,
 239                                                port->phy_id, MII_BMSR);
 240
 241                if (val == 0xffff)
 242                        continue;
 243
 244                up = (val & BMSR_LSTATUS) ? 1 : 0;
 245                if (!(up ^ priv->sw_port_link[i]))
 246                        continue;
 247
 248                priv->sw_port_link[i] = up;
 249
 250                /* link changed */
 251                if (!up) {
 252                        dev_info(dev, "link DOWN on %s\n", port->name);
 253                        writeb_be(ETH_PORTOV_ENABLE_MASK,
 254                                  priv->base + ETH_PORTOV_REG(i));
 255                        writeb_be(ETH_PTCTRL_RXDIS_MASK |
 256                                  ETH_PTCTRL_TXDIS_MASK,
 257                                  priv->base + ETH_PTCTRL_REG(i));
 258                        continue;
 259                }
 260
 261                adv = bcm6368_mdio_read(priv, external_phy,
 262                                        port->phy_id, MII_ADVERTISE);
 263
 264                lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
 265                                        MII_LPA);
 266
 267                /* figure out media and duplex from advertise and LPA values */
 268                media = mii_nway_result(lpa & adv);
 269                duplex = (media & ADVERTISE_FULL) ? 1 : 0;
 270
 271                if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
 272                        speed = 100;
 273                else
 274                        speed = 10;
 275
 276                if (val & BMSR_ESTATEN) {
 277                        adv = bcm6368_mdio_read(priv, external_phy,
 278                                                port->phy_id, MII_CTRL1000);
 279
 280                        lpa = bcm6368_mdio_read(priv, external_phy,
 281                                                port->phy_id, MII_STAT1000);
 282
 283                        if ((adv & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
 284                            (lpa & (LPA_1000FULL | LPA_1000HALF))) {
 285                                speed = 1000;
 286                                duplex = (lpa & LPA_1000FULL);
 287                        }
 288                }
 289
 290                pr_alert("link UP on %s, %dMbps, %s-duplex\n",
 291                         port->name, speed, duplex ? "full" : "half");
 292
 293                override = ETH_PORTOV_ENABLE_MASK |
 294                           ETH_PORTOV_LINKUP_MASK;
 295
 296                if (speed == 1000)
 297                        override |= ETH_PORTOV_1000_MASK;
 298                else if (speed == 100)
 299                        override |= ETH_PORTOV_100_MASK;
 300                if (duplex)
 301                        override |= ETH_PORTOV_FDX_MASK;
 302
 303                writeb_be(override, priv->base + ETH_PORTOV_REG(i));
 304                writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
 305        }
 306
 307        return 0;
 308}
 309
 310static int bcm6368_eth_start(struct udevice *dev)
 311{
 312        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 313        uint8_t i;
 314
 315        /* disable all ports */
 316        for (i = 0; i < priv->num_ports; i++) {
 317                setbits_8(priv->base + ETH_PORTOV_REG(i),
 318                          ETH_PORTOV_ENABLE_MASK);
 319                setbits_8(priv->base + ETH_PTCTRL_REG(i),
 320                          ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
 321                priv->sw_port_link[i] = 0;
 322        }
 323
 324        /* enable external ports */
 325        for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
 326                u8 rgmii_ctrl = ETH_RGMII_CTRL_GMII_CLK_EN;
 327
 328                if (!priv->used_ports[i].used)
 329                        continue;
 330
 331                if (priv->rgmii_override)
 332                        rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
 333                if (priv->rgmii_timing)
 334                        rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
 335
 336                setbits_8(priv->base + ETH_RGMII_CTRL_REG(i), rgmii_ctrl);
 337        }
 338
 339        /* reset mib */
 340        setbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
 341        mdelay(1);
 342        clrbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
 343        mdelay(1);
 344
 345        /* force CPU port state */
 346        setbits_8(priv->base + ETH_IMPOV_REG,
 347                  ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
 348
 349        /* enable switch forward engine */
 350        setbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
 351
 352        /* prepare rx dma buffers */
 353        for (i = 0; i < ETH_RX_DESC; i++) {
 354                int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
 355                                              PKTSIZE_ALIGN);
 356                if (ret < 0)
 357                        break;
 358        }
 359
 360        /* enable dma rx channel */
 361        dma_enable(&priv->rx_dma);
 362
 363        /* enable dma tx channel */
 364        dma_enable(&priv->tx_dma);
 365
 366        /* apply override config for bypass_link ports here. */
 367        for (i = 0; i < priv->num_ports; i++) {
 368                struct bcm_enetsw_port *port;
 369                u8 override;
 370
 371                port = &priv->used_ports[i];
 372                if (!port->used)
 373                        continue;
 374
 375                if (!port->bypass_link)
 376                        continue;
 377
 378                override = ETH_PORTOV_ENABLE_MASK |
 379                           ETH_PORTOV_LINKUP_MASK;
 380
 381                switch (port->force_speed) {
 382                case 1000:
 383                        override |= ETH_PORTOV_1000_MASK;
 384                        break;
 385                case 100:
 386                        override |= ETH_PORTOV_100_MASK;
 387                        break;
 388                case 10:
 389                        break;
 390                default:
 391                        pr_warn("%s: invalid forced speed on port %s\n",
 392                                __func__, port->name);
 393                        break;
 394                }
 395
 396                if (port->force_duplex_full)
 397                        override |= ETH_PORTOV_FDX_MASK;
 398
 399                writeb_be(override, priv->base + ETH_PORTOV_REG(i));
 400                writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
 401        }
 402
 403        bcm6368_eth_adjust_link(dev);
 404
 405        return 0;
 406}
 407
 408static void bcm6368_eth_stop(struct udevice *dev)
 409{
 410        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 411        uint8_t i;
 412
 413        /* disable all ports */
 414        for (i = 0; i < priv->num_ports; i++) {
 415                setbits_8(priv->base + ETH_PORTOV_REG(i),
 416                          ETH_PORTOV_ENABLE_MASK);
 417                setbits_8(priv->base + ETH_PTCTRL_REG(i),
 418                          ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
 419        }
 420
 421        /* disable external ports */
 422        for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
 423                if (!priv->used_ports[i].used)
 424                        continue;
 425
 426                clrbits_8(priv->base + ETH_RGMII_CTRL_REG(i),
 427                          ETH_RGMII_CTRL_GMII_CLK_EN);
 428        }
 429
 430        /* disable CPU port */
 431        clrbits_8(priv->base + ETH_IMPOV_REG,
 432                  ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
 433
 434        /* disable switch forward engine */
 435        clrbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
 436
 437        /* disable dma rx channel */
 438        dma_disable(&priv->rx_dma);
 439
 440        /* disable dma tx channel */
 441        dma_disable(&priv->tx_dma);
 442}
 443
 444static const struct eth_ops bcm6368_eth_ops = {
 445        .free_pkt = bcm6368_eth_free_pkt,
 446        .recv = bcm6368_eth_recv,
 447        .send = bcm6368_eth_send,
 448        .start = bcm6368_eth_start,
 449        .stop = bcm6368_eth_stop,
 450};
 451
 452static const struct udevice_id bcm6368_eth_ids[] = {
 453        { .compatible = "brcm,bcm6368-enet", },
 454        { /* sentinel */ }
 455};
 456
 457static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv, int phy_id)
 458{
 459        uint8_t i;
 460
 461        for (i = 0; i < priv->num_ports; ++i) {
 462                if (!priv->used_ports[i].used)
 463                        continue;
 464                if (priv->used_ports[i].phy_id == phy_id)
 465                        return bcm_enet_port_is_rgmii(i);
 466        }
 467
 468        return true;
 469}
 470
 471static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
 472                                 int reg)
 473{
 474        struct bcm6368_eth_priv *priv = bus->priv;
 475        bool ext = bcm6368_phy_is_external(priv, addr);
 476
 477        return bcm6368_mdio_read(priv, ext, addr, reg);
 478}
 479
 480static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
 481                                  int reg, u16 data)
 482{
 483        struct bcm6368_eth_priv *priv = bus->priv;
 484        bool ext = bcm6368_phy_is_external(priv, addr);
 485
 486        return bcm6368_mdio_write(priv, ext, addr, reg, data);
 487}
 488
 489static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
 490{
 491        struct mii_dev *bus;
 492
 493        bus = mdio_alloc();
 494        if (!bus) {
 495                pr_err("%s: failed to allocate MDIO bus\n", __func__);
 496                return -ENOMEM;
 497        }
 498
 499        bus->read = bcm6368_mii_mdio_read;
 500        bus->write = bcm6368_mii_mdio_write;
 501        bus->priv = priv;
 502        snprintf(bus->name, sizeof(bus->name), "%s", name);
 503
 504        return mdio_register(bus);
 505}
 506
 507static int bcm6368_eth_probe(struct udevice *dev)
 508{
 509        struct eth_pdata *pdata = dev_get_platdata(dev);
 510        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 511        int num_ports, ret, i;
 512        ofnode node;
 513
 514        /* get base address */
 515        priv->base = dev_remap_addr(dev);
 516        if (!priv->base)
 517                return -EINVAL;
 518        pdata->iobase = (phys_addr_t) priv->base;
 519
 520        /* get number of ports */
 521        num_ports = dev_read_u32_default(dev, "brcm,num-ports", ETH_MAX_PORT);
 522        if (!num_ports || num_ports > ETH_MAX_PORT)
 523                return -EINVAL;
 524
 525        /* get dma channels */
 526        ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
 527        if (ret)
 528                return -EINVAL;
 529
 530        ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
 531        if (ret)
 532                return -EINVAL;
 533
 534        /* try to enable clocks */
 535        for (i = 0; ; i++) {
 536                struct clk clk;
 537                int ret;
 538
 539                ret = clk_get_by_index(dev, i, &clk);
 540                if (ret < 0)
 541                        break;
 542
 543                ret = clk_enable(&clk);
 544                if (ret < 0) {
 545                        pr_err("%s: error enabling clock %d\n", __func__, i);
 546                        return ret;
 547                }
 548
 549                ret = clk_free(&clk);
 550                if (ret < 0) {
 551                        pr_err("%s: error freeing clock %d\n", __func__, i);
 552                        return ret;
 553                }
 554        }
 555
 556        /* try to perform resets */
 557        for (i = 0; ; i++) {
 558                struct reset_ctl reset;
 559                int ret;
 560
 561                ret = reset_get_by_index(dev, i, &reset);
 562                if (ret < 0)
 563                        break;
 564
 565                ret = reset_deassert(&reset);
 566                if (ret < 0) {
 567                        pr_err("%s: error deasserting reset %d\n", __func__, i);
 568                        return ret;
 569                }
 570
 571                ret = reset_free(&reset);
 572                if (ret < 0) {
 573                        pr_err("%s: error freeing reset %d\n", __func__, i);
 574                        return ret;
 575                }
 576        }
 577
 578        /* set priv data */
 579        priv->num_ports = num_ports;
 580        if (dev_read_bool(dev, "brcm,rgmii-override"))
 581                priv->rgmii_override = true;
 582        if (dev_read_bool(dev, "brcm,rgmii-timing"))
 583                priv->rgmii_timing = true;
 584
 585        /* get ports */
 586        dev_for_each_subnode(node, dev) {
 587                const char *comp;
 588                const char *label;
 589                unsigned int p;
 590                int phy_id;
 591                int speed;
 592
 593                comp = ofnode_read_string(node, "compatible");
 594                if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
 595                        continue;
 596
 597                p = ofnode_read_u32_default(node, "reg", ETH_MAX_PORT);
 598                if (p >= num_ports)
 599                        return -EINVAL;
 600
 601                label = ofnode_read_string(node, "label");
 602                if (!label) {
 603                        debug("%s: node %s has no label\n", __func__,
 604                              ofnode_get_name(node));
 605                        return -EINVAL;
 606                }
 607
 608                phy_id = ofnode_read_u32_default(node, "brcm,phy-id", -1);
 609
 610                priv->used_ports[p].used = true;
 611                priv->used_ports[p].name = label;
 612                priv->used_ports[p].phy_id = phy_id;
 613
 614                if (ofnode_read_bool(node, "full-duplex"))
 615                        priv->used_ports[p].force_duplex_full = true;
 616                if (ofnode_read_bool(node, "bypass-link"))
 617                        priv->used_ports[p].bypass_link = true;
 618                speed = ofnode_read_u32_default(node, "speed", 0);
 619                if (speed)
 620                        priv->used_ports[p].force_speed = speed;
 621        }
 622
 623        /* init mii bus */
 624        ret = bcm6368_mdio_init(dev->name, priv);
 625        if (ret)
 626                return ret;
 627
 628        /* enable jumbo on all ports */
 629        writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
 630        writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
 631
 632        return 0;
 633}
 634
 635U_BOOT_DRIVER(bcm6368_eth) = {
 636        .name = "bcm6368_eth",
 637        .id = UCLASS_ETH,
 638        .of_match = bcm6368_eth_ids,
 639        .ops = &bcm6368_eth_ops,
 640        .platdata_auto_alloc_size = sizeof(struct eth_pdata),
 641        .priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
 642        .probe = bcm6368_eth_probe,
 643};
 644