diff options
author | Quentin Schulz <quentin.schulz@bootlin.com> | 2018-10-04 14:22:08 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-10-05 23:36:44 +0200 |
commit | 71e32a20cfbf0e53f43117337d355ea505f8f081 (patch) | |
tree | 5ff8e5ac17b1b40fc1f36aa10b6f1939f8ca2033 /drivers/net/ethernet/mscc/ocelot_board.c | |
parent | phy: add driver for Microsemi Ocelot SerDes muxing (diff) | |
download | linux-71e32a20cfbf0e53f43117337d355ea505f8f081.tar.xz linux-71e32a20cfbf0e53f43117337d355ea505f8f081.zip |
net: mscc: ocelot: make use of SerDes PHYs for handling their configuration
Previously, the SerDes muxing was hardcoded to a given mode in the MAC
controller driver. Now, the SerDes muxing is configured within the
Device Tree and is enforced in the MAC controller driver so we can have
a lot of different SerDes configurations.
Make use of the SerDes PHYs in the MAC controller to set up the SerDes
according to the SerDes<->switch port mapping and the communication mode
with the Ethernet PHY.
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mscc/ocelot_board.c')
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot_board.c | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c index dca205e0ef75..953b32677383 100644 --- a/drivers/net/ethernet/mscc/ocelot_board.c +++ b/drivers/net/ethernet/mscc/ocelot_board.c @@ -6,6 +6,7 @@ */ #include <linux/interrupt.h> #include <linux/module.h> +#include <linux/of_net.h> #include <linux/netdevice.h> #include <linux/of_mdio.h> #include <linux/of_platform.h> @@ -253,18 +254,12 @@ static int mscc_ocelot_probe(struct platform_device *pdev) INIT_LIST_HEAD(&ocelot->multicast); ocelot_init(ocelot); - ocelot_rmw(ocelot, HSIO_HW_CFG_DEV1G_4_MODE | - HSIO_HW_CFG_DEV1G_6_MODE | - HSIO_HW_CFG_DEV1G_9_MODE, - HSIO_HW_CFG_DEV1G_4_MODE | - HSIO_HW_CFG_DEV1G_6_MODE | - HSIO_HW_CFG_DEV1G_9_MODE, - HSIO_HW_CFG); - for_each_available_child_of_node(ports, portnp) { struct device_node *phy_node; struct phy_device *phy; struct resource *res; + struct phy *serdes; + enum phy_mode phy_mode; void __iomem *regs; char res_name[8]; u32 port; @@ -289,10 +284,45 @@ static int mscc_ocelot_probe(struct platform_device *pdev) continue; err = ocelot_probe_port(ocelot, port, regs, phy); - if (err) { - dev_err(&pdev->dev, "failed to probe ports\n"); + if (err) + return err; + + err = of_get_phy_mode(portnp); + if (err < 0) + ocelot->ports[port]->phy_mode = PHY_INTERFACE_MODE_NA; + else + ocelot->ports[port]->phy_mode = err; + + switch (ocelot->ports[port]->phy_mode) { + case PHY_INTERFACE_MODE_NA: + continue; + case PHY_INTERFACE_MODE_SGMII: + phy_mode = PHY_MODE_SGMII; + break; + case PHY_INTERFACE_MODE_QSGMII: + phy_mode = PHY_MODE_QSGMII; + break; + default: + dev_err(ocelot->dev, + "invalid phy mode for port%d, (Q)SGMII only\n", + port); + return -EINVAL; + } + + serdes = devm_of_phy_get(ocelot->dev, portnp, NULL); + if (IS_ERR(serdes)) { + err = PTR_ERR(serdes); + if (err == -EPROBE_DEFER) + dev_dbg(ocelot->dev, "deferring probe\n"); + else + dev_err(ocelot->dev, + "missing SerDes phys for port%d\n", + port); + goto err_probe_ports; } + + ocelot->ports[port]->serdes = serdes; } register_netdevice_notifier(&ocelot_netdevice_nb); |