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(&priv->pdev->dev, "link DOWN on %s\n",
 253                                 port->name);
 254                        writeb_be(ETH_PORTOV_ENABLE_MASK,
 255                                  priv->base + ETH_PORTOV_REG(i));
 256                        writeb_be(ETH_PTCTRL_RXDIS_MASK |
 257                                  ETH_PTCTRL_TXDIS_MASK,
 258                                  priv->base + ETH_PTCTRL_REG(i));
 259                        continue;
 260                }
 261
 262                adv = bcm6368_mdio_read(priv, external_phy,
 263                                        port->phy_id, MII_ADVERTISE);
 264
 265                lpa = bcm6368_mdio_read(priv, external_phy, port->phy_id,
 266                                        MII_LPA);
 267
 268                /* figure out media and duplex from advertise and LPA values */
 269                media = mii_nway_result(lpa & adv);
 270                duplex = (media & ADVERTISE_FULL) ? 1 : 0;
 271
 272                if (media & (ADVERTISE_100FULL | ADVERTISE_100HALF))
 273                        speed = 100;
 274                else
 275                        speed = 10;
 276
 277                if (val & BMSR_ESTATEN) {
 278                        adv = bcm6368_mdio_read(priv, external_phy,
 279                                                port->phy_id, MII_CTRL1000);
 280
 281                        lpa = bcm6368_mdio_read(priv, external_phy,
 282                                                port->phy_id, MII_STAT1000);
 283
 284                        if ((adv & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) &&
 285                            (lpa & (LPA_1000FULL | LPA_1000HALF))) {
 286                                speed = 1000;
 287                                duplex = (lpa & LPA_1000FULL);
 288                        }
 289                }
 290
 291                pr_alert("link UP on %s, %dMbps, %s-duplex\n",
 292                         port->name, speed, duplex ? "full" : "half");
 293
 294                override = ETH_PORTOV_ENABLE_MASK |
 295                           ETH_PORTOV_LINKUP_MASK;
 296
 297                if (speed == 1000)
 298                        override |= ETH_PORTOV_1000_MASK;
 299                else if (speed == 100)
 300                        override |= ETH_PORTOV_100_MASK;
 301                if (duplex)
 302                        override |= ETH_PORTOV_FDX_MASK;
 303
 304                writeb_be(override, priv->base + ETH_PORTOV_REG(i));
 305                writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
 306        }
 307
 308        return 0;
 309}
 310
 311static int bcm6368_eth_start(struct udevice *dev)
 312{
 313        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 314        uint8_t i;
 315
 316        /* disable all ports */
 317        for (i = 0; i < priv->num_ports; i++) {
 318                setbits_8(priv->base + ETH_PORTOV_REG(i),
 319                          ETH_PORTOV_ENABLE_MASK);
 320                setbits_8(priv->base + ETH_PTCTRL_REG(i),
 321                          ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
 322                priv->sw_port_link[i] = 0;
 323        }
 324
 325        /* enable external ports */
 326        for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
 327                u8 rgmii_ctrl = ETH_RGMII_CTRL_GMII_CLK_EN;
 328
 329                if (!priv->used_ports[i].used)
 330                        continue;
 331
 332                if (priv->rgmii_override)
 333                        rgmii_ctrl |= ETH_RGMII_CTRL_MII_OVERRIDE_EN;
 334                if (priv->rgmii_timing)
 335                        rgmii_ctrl |= ETH_RGMII_CTRL_TIMING_SEL_EN;
 336
 337                setbits_8(priv->base + ETH_RGMII_CTRL_REG(i), rgmii_ctrl);
 338        }
 339
 340        /* reset mib */
 341        setbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
 342        mdelay(1);
 343        clrbits_8(priv->base + ETH_GMCR_REG, ETH_GMCR_RST_MIB_MASK);
 344        mdelay(1);
 345
 346        /* force CPU port state */
 347        setbits_8(priv->base + ETH_IMPOV_REG,
 348                  ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
 349
 350        /* enable switch forward engine */
 351        setbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
 352
 353        /* prepare rx dma buffers */
 354        for (i = 0; i < ETH_RX_DESC; i++) {
 355                int ret = dma_prepare_rcv_buf(&priv->rx_dma, net_rx_packets[i],
 356                                              PKTSIZE_ALIGN);
 357                if (ret < 0)
 358                        break;
 359        }
 360
 361        /* enable dma rx channel */
 362        dma_enable(&priv->rx_dma);
 363
 364        /* enable dma tx channel */
 365        dma_enable(&priv->tx_dma);
 366
 367        /* apply override config for bypass_link ports here. */
 368        for (i = 0; i < priv->num_ports; i++) {
 369                struct bcm_enetsw_port *port;
 370                u8 override;
 371
 372                port = &priv->used_ports[i];
 373                if (!port->used)
 374                        continue;
 375
 376                if (!port->bypass_link)
 377                        continue;
 378
 379                override = ETH_PORTOV_ENABLE_MASK |
 380                           ETH_PORTOV_LINKUP_MASK;
 381
 382                switch (port->force_speed) {
 383                case 1000:
 384                        override |= ETH_PORTOV_1000_MASK;
 385                        break;
 386                case 100:
 387                        override |= ETH_PORTOV_100_MASK;
 388                        break;
 389                case 10:
 390                        break;
 391                default:
 392                        pr_warn("%s: invalid forced speed on port %s\n",
 393                                __func__, port->name);
 394                        break;
 395                }
 396
 397                if (port->force_duplex_full)
 398                        override |= ETH_PORTOV_FDX_MASK;
 399
 400                writeb_be(override, priv->base + ETH_PORTOV_REG(i));
 401                writeb_be(0, priv->base + ETH_PTCTRL_REG(i));
 402        }
 403
 404        bcm6368_eth_adjust_link(dev);
 405
 406        return 0;
 407}
 408
 409static void bcm6368_eth_stop(struct udevice *dev)
 410{
 411        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 412        uint8_t i;
 413
 414        /* disable all ports */
 415        for (i = 0; i < priv->num_ports; i++) {
 416                setbits_8(priv->base + ETH_PORTOV_REG(i),
 417                          ETH_PORTOV_ENABLE_MASK);
 418                setbits_8(priv->base + ETH_PTCTRL_REG(i),
 419                          ETH_PTCTRL_RXDIS_MASK | ETH_PTCTRL_TXDIS_MASK);
 420        }
 421
 422        /* disable external ports */
 423        for (i = ETH_RGMII_PORT0; i < priv->num_ports; i++) {
 424                if (!priv->used_ports[i].used)
 425                        continue;
 426
 427                clrbits_8(priv->base + ETH_RGMII_CTRL_REG(i),
 428                          ETH_RGMII_CTRL_GMII_CLK_EN);
 429        }
 430
 431        /* disable CPU port */
 432        clrbits_8(priv->base + ETH_IMPOV_REG,
 433                  ETH_IMPOV_FORCE_MASK | ETH_IMPOV_LINKUP_MASK);
 434
 435        /* disable switch forward engine */
 436        clrbits_8(priv->base + ETH_SWMODE_REG, ETH_SWMODE_FWD_EN_MASK);
 437
 438        /* disable dma rx channel */
 439        dma_disable(&priv->rx_dma);
 440
 441        /* disable dma tx channel */
 442        dma_disable(&priv->tx_dma);
 443}
 444
 445static const struct eth_ops bcm6368_eth_ops = {
 446        .free_pkt = bcm6368_eth_free_pkt,
 447        .recv = bcm6368_eth_recv,
 448        .send = bcm6368_eth_send,
 449        .start = bcm6368_eth_start,
 450        .stop = bcm6368_eth_stop,
 451};
 452
 453static const struct udevice_id bcm6368_eth_ids[] = {
 454        { .compatible = "brcm,bcm6368-enet", },
 455        { /* sentinel */ }
 456};
 457
 458static bool bcm6368_phy_is_external(struct bcm6368_eth_priv *priv, int phy_id)
 459{
 460        uint8_t i;
 461
 462        for (i = 0; i < priv->num_ports; ++i) {
 463                if (!priv->used_ports[i].used)
 464                        continue;
 465                if (priv->used_ports[i].phy_id == phy_id)
 466                        return bcm_enet_port_is_rgmii(i);
 467        }
 468
 469        return true;
 470}
 471
 472static int bcm6368_mii_mdio_read(struct mii_dev *bus, int addr, int devaddr,
 473                                 int reg)
 474{
 475        struct bcm6368_eth_priv *priv = bus->priv;
 476        bool ext = bcm6368_phy_is_external(priv, addr);
 477
 478        return bcm6368_mdio_read(priv, ext, addr, reg);
 479}
 480
 481static int bcm6368_mii_mdio_write(struct mii_dev *bus, int addr, int devaddr,
 482                                  int reg, u16 data)
 483{
 484        struct bcm6368_eth_priv *priv = bus->priv;
 485        bool ext = bcm6368_phy_is_external(priv, addr);
 486
 487        return bcm6368_mdio_write(priv, ext, addr, reg, data);
 488}
 489
 490static int bcm6368_mdio_init(const char *name, struct bcm6368_eth_priv *priv)
 491{
 492        struct mii_dev *bus;
 493
 494        bus = mdio_alloc();
 495        if (!bus) {
 496                pr_err("%s: failed to allocate MDIO bus\n", __func__);
 497                return -ENOMEM;
 498        }
 499
 500        bus->read = bcm6368_mii_mdio_read;
 501        bus->write = bcm6368_mii_mdio_write;
 502        bus->priv = priv;
 503        snprintf(bus->name, sizeof(bus->name), "%s", name);
 504
 505        return mdio_register(bus);
 506}
 507
 508static int bcm6368_eth_probe(struct udevice *dev)
 509{
 510        struct eth_pdata *pdata = dev_get_platdata(dev);
 511        struct bcm6368_eth_priv *priv = dev_get_priv(dev);
 512        int num_ports, ret, i;
 513        ofnode node;
 514
 515        /* get base address */
 516        priv->base = dev_remap_addr(dev);
 517        if (!priv->base)
 518                return -EINVAL;
 519        pdata->iobase = (phys_addr_t) priv->base;
 520
 521        /* get number of ports */
 522        num_ports = dev_read_u32_default(dev, "brcm,num-ports", ETH_MAX_PORT);
 523        if (!num_ports || num_ports > ETH_MAX_PORT)
 524                return -EINVAL;
 525
 526        /* get dma channels */
 527        ret = dma_get_by_name(dev, "tx", &priv->tx_dma);
 528        if (ret)
 529                return -EINVAL;
 530
 531        ret = dma_get_by_name(dev, "rx", &priv->rx_dma);
 532        if (ret)
 533                return -EINVAL;
 534
 535        /* try to enable clocks */
 536        for (i = 0; ; i++) {
 537                struct clk clk;
 538                int ret;
 539
 540                ret = clk_get_by_index(dev, i, &clk);
 541                if (ret < 0)
 542                        break;
 543
 544                ret = clk_enable(&clk);
 545                if (ret < 0) {
 546                        pr_err("%s: error enabling clock %d\n", __func__, i);
 547                        return ret;
 548                }
 549
 550                ret = clk_free(&clk);
 551                if (ret < 0) {
 552                        pr_err("%s: error freeing clock %d\n", __func__, i);
 553                        return ret;
 554                }
 555        }
 556
 557        /* try to perform resets */
 558        for (i = 0; ; i++) {
 559                struct reset_ctl reset;
 560                int ret;
 561
 562                ret = reset_get_by_index(dev, i, &reset);
 563                if (ret < 0)
 564                        break;
 565
 566                ret = reset_deassert(&reset);
 567                if (ret < 0) {
 568                        pr_err("%s: error deasserting reset %d\n", __func__, i);
 569                        return ret;
 570                }
 571
 572                ret = reset_free(&reset);
 573                if (ret < 0) {
 574                        pr_err("%s: error freeing reset %d\n", __func__, i);
 575                        return ret;
 576                }
 577        }
 578
 579        /* set priv data */
 580        priv->num_ports = num_ports;
 581        if (dev_read_bool(dev, "brcm,rgmii-override"))
 582                priv->rgmii_override = true;
 583        if (dev_read_bool(dev, "brcm,rgmii-timing"))
 584                priv->rgmii_timing = true;
 585
 586        /* get ports */
 587        dev_for_each_subnode(node, dev) {
 588                const char *comp;
 589                const char *label;
 590                unsigned int p;
 591                int phy_id;
 592                int speed;
 593
 594                comp = ofnode_read_string(node, "compatible");
 595                if (!comp || memcmp(comp, ETH_PORT_STR, sizeof(ETH_PORT_STR)))
 596                        continue;
 597
 598                p = ofnode_read_u32_default(node, "reg", ETH_MAX_PORT);
 599                if (p >= num_ports)
 600                        return -EINVAL;
 601
 602                label = ofnode_read_string(node, "label");
 603                if (!label) {
 604                        debug("%s: node %s has no label\n", __func__,
 605                              ofnode_get_name(node));
 606                        return -EINVAL;
 607                }
 608
 609                phy_id = ofnode_read_u32_default(node, "brcm,phy-id", -1);
 610
 611                priv->used_ports[p].used = true;
 612                priv->used_ports[p].name = label;
 613                priv->used_ports[p].phy_id = phy_id;
 614
 615                if (ofnode_read_bool(node, "full-duplex"))
 616                        priv->used_ports[p].force_duplex_full = true;
 617                if (ofnode_read_bool(node, "bypass-link"))
 618                        priv->used_ports[p].bypass_link = true;
 619                speed = ofnode_read_u32_default(node, "speed", 0);
 620                if (speed)
 621                        priv->used_ports[p].force_speed = speed;
 622        }
 623
 624        /* init mii bus */
 625        ret = bcm6368_mdio_init(dev->name, priv);
 626        if (ret)
 627                return ret;
 628
 629        /* enable jumbo on all ports */
 630        writel_be(0x1ff, priv->base + ETH_JMBCTL_PORT_REG);
 631        writew_be(9728, priv->base + ETH_JMBCTL_MAXSIZE_REG);
 632
 633        return 0;
 634}
 635
 636U_BOOT_DRIVER(bcm6368_eth) = {
 637        .name = "bcm6368_eth",
 638        .id = UCLASS_ETH,
 639        .of_match = bcm6368_eth_ids,
 640        .ops = &bcm6368_eth_ops,
 641        .platdata_auto_alloc_size = sizeof(struct eth_pdata),
 642        .priv_auto_alloc_size = sizeof(struct bcm6368_eth_priv),
 643        .probe = bcm6368_eth_probe,
 644};
 645