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 */ 113 struct 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 */ 125 struct 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 140 static inline bool bcm_enet_port_is_rgmii(int portid) 141 { 142 return portid >= ETH_RGMII_PORT0; 143 } 144 145 static 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 165 static 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 187 static 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 194 static 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 201 static 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 214 static 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 307 static 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 405 static 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 441 static 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 449 static const struct udevice_id bcm6368_eth_ids[] = { 450 { .compatible = "brcm,bcm6368-enet", }, 451 { /* sentinel */ } 452 }; 453 454 static 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 468 static 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 477 static 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 486 static 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 504 static 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 632 U_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