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