Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-enetc-add-port-mdio-support-for-both-i-mx94-and-i-mx95'

Wei Fang says:

====================
net: enetc: add port MDIO support for both i.MX94 and i.MX95

The NETC IP has one external master MDIO interface (eMDIO) for managing
external PHYs, all ENETC ports share this eMDIO. The EMDIO function and
the ENETC port MDIO are the virtual ports of this eMDIO, ENETC can use
these virtual ports to access their PHYs. The difference is that EMDIO
function is a 'global port', it can access all the PHYs on the eMDIO, so
it provides a means for different software modules to share a single set
of MDIO signals to access their PHYs.

The ENETC port MDIO can only access its own external PHY. Furthermore,
its PHY address must be set to its corresponding LaBCR register in IERB
module, which is is a 64 KB size page containing registers that are used
for pre-boot initialization for all NETC PCIe functions. And this IERB
is owned by the host OS and it will be locked after the initialization,
so it cannot be configured at running time any more. The port MDIO can
only work properly when the PHY address accessed by it matches the value
of its corresponding LaBCR[MDIO_PHYAD_PRTAD]. Otherwise, the MDIO access
by the port MDIO will not take effect.

Note that the same PHY is either controlled by port MDIO or by the EMDIO
function. The netc-blk-ctrl driver will only set the PHY address in the
LaBCR register corresponding to the ENETC when the ENETC node contains
an mdio child node, and the ENETC driver will only create the port MDIO
bus then. An example in DTS is as follows, the EMDIO function will not\
access this PHY.

enetc_port0 {
phy-handle = <&ethphy0>;
phy-mode = "rgmii-id";

mdio {
#address-cells = <1>;
#size-cells = <0>;

ethphy0: ethernet-phy@1 {
reg = <1>;
};
};
};

If users want to use EMDIO funtion to manage the PHY, they only need to
place the PHY node in the emdio node. The same PHY must not be placed
simultaneously within the ENETC node. An example in DTS to use EMDIO
is as below.

netc_emdio {
ethphy0: ethernet-phy@1 {
reg = <1>;
};

ethphy2: ethernet-phy@8 {
reg = <8>;
};
};

In the host OS, when there are multiple ENETCs, they can all access their
PHYs using their own port MDIO, or they can all access their PHYs using
the EMDIO function, or they can partially use port MDIO and partially use
the EMDIO function.

Another typical use case of port MDIO is the Jailhouse usage. An ENETC is
assigned to a guest OS. The EMDIO function will be unavailable in the
guest OS because EMDIO is controlled by the host OS. Therefore, the ENETC
can use its port MDIO to manage its external PHY in this situation. In
this use case, the host OS's root dtb will disable the ENETC node, so the
host OS's ENETC driver will not probe the ENETC and its PHY.

In addition, this series also adds the internal MDIO bus support, each
ENETC has an internal MDIO interface for managing on-die PHY (PCS) if it
has PCS layer.
====================

Link: https://patch.msgid.link/20251119102557.1041881-1-wei.fang@nxp.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+215 -3
+6
drivers/net/ethernet/freescale/enetc/enetc4_hw.h
··· 170 170 /* Port MAC 0/1 Maximum Frame Length Register */ 171 171 #define ENETC4_PM_MAXFRM(mac) (0x5014 + (mac) * 0x400) 172 172 173 + /* Port internal MDIO base address, use to access PCS */ 174 + #define ENETC4_PM_IMDIO_BASE 0x5030 175 + 173 176 /* Port MAC 0/1 Pause Quanta Register */ 174 177 #define ENETC4_PM_PAUSE_QUANTA(mac) (0x5054 + (mac) * 0x400) 175 178 ··· 200 197 #define SSP_10M 1 201 198 #define SSP_1G 2 202 199 #define PM_IF_MODE_ENA BIT(15) 200 + 201 + /* Port external MDIO Base address, use to access off-chip PHY */ 202 + #define ENETC4_EMDIO_BASE 0x5c00 203 203 204 204 /**********************ENETC Pseudo MAC port registers************************/ 205 205 /* Port pseudo MAC receive octets counter (64-bit) */
+12 -2
drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
··· 176 176 bus->parent = dev; 177 177 mdio_priv = bus->priv; 178 178 mdio_priv->hw = &pf->si->hw; 179 - mdio_priv->mdio_base = ENETC_EMDIO_BASE; 179 + 180 + if (is_enetc_rev1(pf->si)) 181 + mdio_priv->mdio_base = ENETC_EMDIO_BASE; 182 + else 183 + mdio_priv->mdio_base = ENETC4_EMDIO_BASE; 184 + 180 185 snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); 181 186 182 187 err = of_mdiobus_register(bus, np); ··· 226 221 bus->phy_mask = ~0; 227 222 mdio_priv = bus->priv; 228 223 mdio_priv->hw = &pf->si->hw; 229 - mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE; 224 + 225 + if (is_enetc_rev1(pf->si)) 226 + mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE; 227 + else 228 + mdio_priv->mdio_base = ENETC4_PM_IMDIO_BASE; 229 + 230 230 snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev)); 231 231 232 232 err = mdiobus_register(bus);
+197 -1
drivers/net/ethernet/freescale/enetc/netc_blk_ctrl.c
··· 67 67 #define IERB_EMDIOFAUXR 0x344 68 68 #define IERB_T0FAUXR 0x444 69 69 #define IERB_ETBCR(a) (0x300c + 0x100 * (a)) 70 + #define IERB_LBCR(a) (0x1010 + 0x40 * (a)) 71 + #define LBCR_MDIO_PHYAD_PRTAD(addr) (((addr) & 0x1f) << 8) 72 + 70 73 #define IERB_EFAUXR(a) (0x3044 + 0x100 * (a)) 71 74 #define IERB_VFAUXR(a) (0x4004 + 0x40 * (a)) 72 75 #define FAUXR_LDID GENMASK(3, 0) ··· 325 322 1000, 100000, true, priv->prb, PRB_NETCRR); 326 323 } 327 324 325 + static int netc_get_phy_addr(struct device_node *np) 326 + { 327 + struct device_node *mdio_node, *phy_node; 328 + u32 addr = 0; 329 + int err = 0; 330 + 331 + mdio_node = of_get_child_by_name(np, "mdio"); 332 + if (!mdio_node) 333 + return 0; 334 + 335 + phy_node = of_get_next_child(mdio_node, NULL); 336 + if (!phy_node) 337 + goto of_put_mdio_node; 338 + 339 + err = of_property_read_u32(phy_node, "reg", &addr); 340 + if (err) 341 + goto of_put_phy_node; 342 + 343 + if (addr >= PHY_MAX_ADDR) 344 + err = -EINVAL; 345 + 346 + of_put_phy_node: 347 + of_node_put(phy_node); 348 + 349 + of_put_mdio_node: 350 + of_node_put(mdio_node); 351 + 352 + return err ? err : addr; 353 + } 354 + 355 + static int netc_parse_emdio_phy_mask(struct device_node *np, u32 *phy_mask) 356 + { 357 + u32 mask = 0; 358 + 359 + for_each_child_of_node_scoped(np, child) { 360 + u32 addr; 361 + int err; 362 + 363 + err = of_property_read_u32(child, "reg", &addr); 364 + if (err) 365 + return err; 366 + 367 + if (addr >= PHY_MAX_ADDR) 368 + return -EINVAL; 369 + 370 + mask |= BIT(addr); 371 + } 372 + 373 + *phy_mask = mask; 374 + 375 + return 0; 376 + } 377 + 378 + static int netc_get_emdio_phy_mask(struct device_node *np, u32 *phy_mask) 379 + { 380 + for_each_child_of_node_scoped(np, child) { 381 + for_each_child_of_node_scoped(child, gchild) { 382 + if (!of_device_is_compatible(gchild, "pci1131,ee00")) 383 + continue; 384 + 385 + return netc_parse_emdio_phy_mask(gchild, phy_mask); 386 + } 387 + } 388 + 389 + return 0; 390 + } 391 + 392 + static int imx95_enetc_mdio_phyaddr_config(struct platform_device *pdev) 393 + { 394 + struct netc_blk_ctrl *priv = platform_get_drvdata(pdev); 395 + struct device_node *np = pdev->dev.of_node; 396 + struct device *dev = &pdev->dev; 397 + int bus_devfn, addr, err; 398 + u32 phy_mask = 0; 399 + 400 + err = netc_get_emdio_phy_mask(np, &phy_mask); 401 + if (err) { 402 + dev_err(dev, "Failed to get PHY address mask\n"); 403 + return err; 404 + } 405 + 406 + /* Update the port EMDIO PHY address through parsing phy properties. 407 + * This is needed when using the port EMDIO but it's harmless when 408 + * using the central EMDIO. So apply it on all cases. 409 + */ 410 + for_each_child_of_node_scoped(np, child) { 411 + for_each_child_of_node_scoped(child, gchild) { 412 + if (!of_device_is_compatible(gchild, "pci1131,e101")) 413 + continue; 414 + 415 + bus_devfn = netc_of_pci_get_bus_devfn(gchild); 416 + if (bus_devfn < 0) { 417 + dev_err(dev, "Failed to get BDF number\n"); 418 + return bus_devfn; 419 + } 420 + 421 + addr = netc_get_phy_addr(gchild); 422 + if (addr < 0) { 423 + dev_err(dev, "Failed to get PHY address\n"); 424 + return addr; 425 + } 426 + 427 + if (phy_mask & BIT(addr)) { 428 + dev_err(dev, 429 + "Find same PHY address in EMDIO and ENETC node\n"); 430 + return -EINVAL; 431 + } 432 + 433 + /* The default value of LaBCR[MDIO_PHYAD_PRTAD ] is 434 + * 0, so no need to set the register. 435 + */ 436 + if (!addr) 437 + continue; 438 + 439 + switch (bus_devfn) { 440 + case IMX95_ENETC0_BUS_DEVFN: 441 + netc_reg_write(priv->ierb, IERB_LBCR(0), 442 + LBCR_MDIO_PHYAD_PRTAD(addr)); 443 + break; 444 + case IMX95_ENETC1_BUS_DEVFN: 445 + netc_reg_write(priv->ierb, IERB_LBCR(1), 446 + LBCR_MDIO_PHYAD_PRTAD(addr)); 447 + break; 448 + case IMX95_ENETC2_BUS_DEVFN: 449 + netc_reg_write(priv->ierb, IERB_LBCR(2), 450 + LBCR_MDIO_PHYAD_PRTAD(addr)); 451 + break; 452 + default: 453 + break; 454 + } 455 + } 456 + } 457 + 458 + return 0; 459 + } 460 + 328 461 static int imx95_ierb_init(struct platform_device *pdev) 329 462 { 330 463 struct netc_blk_ctrl *priv = platform_get_drvdata(pdev); ··· 488 349 /* NETC TIMER */ 489 350 netc_reg_write(priv->ierb, IERB_T0FAUXR, 7); 490 351 491 - return 0; 352 + return imx95_enetc_mdio_phyaddr_config(pdev); 492 353 } 493 354 494 355 static int imx94_get_enetc_id(struct device_node *np) ··· 563 424 return 0; 564 425 } 565 426 427 + static int imx94_enetc_mdio_phyaddr_config(struct netc_blk_ctrl *priv, 428 + struct device_node *np, 429 + u32 phy_mask) 430 + { 431 + struct device *dev = &priv->pdev->dev; 432 + int bus_devfn, addr; 433 + 434 + bus_devfn = netc_of_pci_get_bus_devfn(np); 435 + if (bus_devfn < 0) { 436 + dev_err(dev, "Failed to get BDF number\n"); 437 + return bus_devfn; 438 + } 439 + 440 + addr = netc_get_phy_addr(np); 441 + if (addr <= 0) { 442 + dev_err(dev, "Failed to get PHY address\n"); 443 + return addr; 444 + } 445 + 446 + if (phy_mask & BIT(addr)) { 447 + dev_err(dev, 448 + "Find same PHY address in EMDIO and ENETC node\n"); 449 + return -EINVAL; 450 + } 451 + 452 + switch (bus_devfn) { 453 + case IMX94_ENETC0_BUS_DEVFN: 454 + netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC0_LINK), 455 + LBCR_MDIO_PHYAD_PRTAD(addr)); 456 + break; 457 + case IMX94_ENETC1_BUS_DEVFN: 458 + netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC1_LINK), 459 + LBCR_MDIO_PHYAD_PRTAD(addr)); 460 + break; 461 + case IMX94_ENETC2_BUS_DEVFN: 462 + netc_reg_write(priv->ierb, IERB_LBCR(IMX94_ENETC2_LINK), 463 + LBCR_MDIO_PHYAD_PRTAD(addr)); 464 + break; 465 + default: 466 + break; 467 + } 468 + 469 + return 0; 470 + } 471 + 566 472 static int imx94_ierb_init(struct platform_device *pdev) 567 473 { 568 474 struct netc_blk_ctrl *priv = platform_get_drvdata(pdev); 569 475 struct device_node *np = pdev->dev.of_node; 476 + u32 phy_mask = 0; 570 477 int err; 478 + 479 + err = netc_get_emdio_phy_mask(np, &phy_mask); 480 + if (err) { 481 + dev_err(&pdev->dev, "Failed to get PHY address mask\n"); 482 + return err; 483 + } 571 484 572 485 for_each_child_of_node_scoped(np, child) { 573 486 for_each_child_of_node_scoped(child, gchild) { ··· 627 436 continue; 628 437 629 438 err = imx94_enetc_update_tid(priv, gchild); 439 + if (err) 440 + return err; 441 + 442 + err = imx94_enetc_mdio_phyaddr_config(priv, gchild, 443 + phy_mask); 630 444 if (err) 631 445 return err; 632 446 }