summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mscc/ocelot.c
diff options
context:
space:
mode:
authorColin Foster <colin.foster@in-advantage.com>2023-03-17 19:54:11 +0100
committerDavid S. Miller <davem@davemloft.net>2023-03-20 10:08:48 +0100
commitdfca93ed51a7cf8bfda876705816a5e55381ac4a (patch)
tree6bef022dda248192576aceb57ce33ab61a17b425 /drivers/net/ethernet/mscc/ocelot.c
parentnet: mscc: ocelot: expose generic phylink_mac_config routine (diff)
downloadlinux-dfca93ed51a7cf8bfda876705816a5e55381ac4a.tar.xz
linux-dfca93ed51a7cf8bfda876705816a5e55381ac4a.zip
net: mscc: ocelot: expose serdes configuration function
During chip initialization, ports that use SGMII / QSGMII to interface to external phys need to be configured on the VSC7513 and VSC7514. Expose this configuration routine, so it can be used by DSA drivers. Signed-off-by: Colin Foster <colin.foster@in-advantage.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mscc/ocelot.c')
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 8292e93a3782..1502bb2c8ea7 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -7,6 +7,7 @@
#include <linux/dsa/ocelot.h>
#include <linux/if_bridge.h>
#include <linux/iopoll.h>
+#include <linux/phy/phy.h>
#include <soc/mscc/ocelot_hsio.h>
#include <soc/mscc/ocelot_vcap.h>
#include "ocelot.h"
@@ -809,6 +810,45 @@ static int ocelot_port_flush(struct ocelot *ocelot, int port)
return err;
}
+int ocelot_port_configure_serdes(struct ocelot *ocelot, int port,
+ struct device_node *portnp)
+{
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+ struct device *dev = ocelot->dev;
+ int err;
+
+ /* Ensure clock signals and speed are set on all QSGMII links */
+ if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_QSGMII)
+ ocelot_port_rmwl(ocelot_port, 0,
+ DEV_CLOCK_CFG_MAC_TX_RST |
+ DEV_CLOCK_CFG_MAC_RX_RST,
+ DEV_CLOCK_CFG);
+
+ if (ocelot_port->phy_mode != PHY_INTERFACE_MODE_INTERNAL) {
+ struct phy *serdes = of_phy_get(portnp, NULL);
+
+ if (IS_ERR(serdes)) {
+ err = PTR_ERR(serdes);
+ dev_err_probe(dev, err,
+ "missing SerDes phys for port %d\n",
+ port);
+ return err;
+ }
+
+ err = phy_set_mode_ext(serdes, PHY_MODE_ETHERNET,
+ ocelot_port->phy_mode);
+ of_phy_put(serdes);
+ if (err) {
+ dev_err(dev, "Could not SerDes mode on port %d: %pe\n",
+ port, ERR_PTR(err));
+ return err;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ocelot_port_configure_serdes);
+
void ocelot_phylink_mac_config(struct ocelot *ocelot, int port,
unsigned int link_an_mode,
const struct phylink_link_state *state)