From 672faa7bbf6014a301b6edc477918af445c92ce2 Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:07 -0700 Subject: [PATCH 1/9] phy: phy-ocelot-serdes: add ability to be used in a non-syscon configuration The phy-ocelot-serdes module has exclusively been used in a syscon setup, from an internal CPU. The addition of external control of ocelot switches via an existing MFD implementation means that syscon is no longer the only interface that phy-ocelot-serdes will see. In the MFD configuration, an IORESOURCE_REG resource will exist for the device. Utilize this resource to be able to function in both syscon and non-syscon configurations. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/phy/mscc/phy-ocelot-serdes.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/phy/mscc/phy-ocelot-serdes.c b/drivers/phy/mscc/phy-ocelot-serdes.c index 76f596365176..d9443e865a78 100644 --- a/drivers/phy/mscc/phy-ocelot-serdes.c +++ b/drivers/phy/mscc/phy-ocelot-serdes.c @@ -494,6 +494,7 @@ static int serdes_probe(struct platform_device *pdev) { struct phy_provider *provider; struct serdes_ctrl *ctrl; + struct resource *res; unsigned int i; int ret; @@ -503,6 +504,14 @@ static int serdes_probe(struct platform_device *pdev) ctrl->dev = &pdev->dev; ctrl->regs = syscon_node_to_regmap(pdev->dev.parent->of_node); + if (IS_ERR(ctrl->regs)) { + /* Fall back to using IORESOURCE_REG, if possible */ + res = platform_get_resource(pdev, IORESOURCE_REG, 0); + if (res) + ctrl->regs = dev_get_regmap(ctrl->dev->parent, + res->name); + } + if (IS_ERR(ctrl->regs)) return PTR_ERR(ctrl->regs); From c21ff0939d1d9af1acdf0bf420f206ad3bad2c92 Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:08 -0700 Subject: [PATCH 2/9] mfd: ocelot: add ocelot-serdes capability Add support for the Ocelot SERDES module to support functionality of all non-internal phy ports. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/mfd/ocelot-core.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/mfd/ocelot-core.c b/drivers/mfd/ocelot-core.c index e1772ff00cad..9cccf54fc9c8 100644 --- a/drivers/mfd/ocelot-core.c +++ b/drivers/mfd/ocelot-core.c @@ -45,6 +45,9 @@ #define VSC7512_SIO_CTRL_RES_START 0x710700f8 #define VSC7512_SIO_CTRL_RES_SIZE 0x00000100 +#define VSC7512_HSIO_RES_START 0x710d0000 +#define VSC7512_HSIO_RES_SIZE 0x00000128 + #define VSC7512_ANA_RES_START 0x71880000 #define VSC7512_ANA_RES_SIZE 0x00010000 @@ -129,8 +132,13 @@ static const struct resource vsc7512_sgpio_resources[] = { DEFINE_RES_REG_NAMED(VSC7512_SIO_CTRL_RES_START, VSC7512_SIO_CTRL_RES_SIZE, "gcb_sio"), }; +static const struct resource vsc7512_serdes_resources[] = { + DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"), +}; + static const struct resource vsc7512_switch_resources[] = { DEFINE_RES_REG_NAMED(VSC7512_ANA_RES_START, VSC7512_ANA_RES_SIZE, "ana"), + DEFINE_RES_REG_NAMED(VSC7512_HSIO_RES_START, VSC7512_HSIO_RES_SIZE, "hsio"), DEFINE_RES_REG_NAMED(VSC7512_QS_RES_START, VSC7512_QS_RES_SIZE, "qs"), DEFINE_RES_REG_NAMED(VSC7512_QSYS_RES_START, VSC7512_QSYS_RES_SIZE, "qsys"), DEFINE_RES_REG_NAMED(VSC7512_REW_RES_START, VSC7512_REW_RES_SIZE, "rew"), @@ -176,6 +184,11 @@ static const struct mfd_cell vsc7512_devs[] = { .use_of_reg = true, .num_resources = ARRAY_SIZE(vsc7512_miim1_resources), .resources = vsc7512_miim1_resources, + }, { + .name = "ocelot-serdes", + .of_compatible = "mscc,vsc7514-serdes", + .num_resources = ARRAY_SIZE(vsc7512_serdes_resources), + .resources = vsc7512_serdes_resources, }, { .name = "ocelot-ext-switch", .of_compatible = "mscc,vsc7512-switch", From fec53f44945877c8627da4d3ad70e3ac7e204f38 Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:09 -0700 Subject: [PATCH 3/9] net: mscc: ocelot: expose ocelot_pll5_init routine Ocelot chips have an internal PLL that must be used when communicating through external phys. Expose the init routine, so it can be used by other drivers. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 31 ++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_vsc7514.c | 30 --------------------- include/soc/mscc/ocelot.h | 2 ++ 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 08acb7b89086..9b8403e29445 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "ocelot.h" #include "ocelot_vcap.h" @@ -211,6 +212,36 @@ static void ocelot_mact_init(struct ocelot *ocelot) ocelot_write(ocelot, MACACCESS_CMD_INIT, ANA_TABLES_MACACCESS); } +void ocelot_pll5_init(struct ocelot *ocelot) +{ + /* Configure PLL5. This will need a proper CCF driver + * The values are coming from the VTSS API for Ocelot + */ + regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4, + HSIO_PLL5G_CFG4_IB_CTRL(0x7600) | + HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8)); + regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0, + HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) | + HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) | + HSIO_PLL5G_CFG0_ENA_BIAS | + HSIO_PLL5G_CFG0_ENA_VCO_BUF | + HSIO_PLL5G_CFG0_ENA_CP1 | + HSIO_PLL5G_CFG0_SELCPI(2) | + HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) | + HSIO_PLL5G_CFG0_SELBGV820(4) | + HSIO_PLL5G_CFG0_DIV4 | + HSIO_PLL5G_CFG0_ENA_CLKTREE | + HSIO_PLL5G_CFG0_ENA_LANE); + regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2, + HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET | + HSIO_PLL5G_CFG2_EN_RESET_OVERRUN | + HSIO_PLL5G_CFG2_GAIN_TEST(0x8) | + HSIO_PLL5G_CFG2_ENA_AMPCTRL | + HSIO_PLL5G_CFG2_PWD_AMPCTRL_N | + HSIO_PLL5G_CFG2_AMPC_SEL(0x10)); +} +EXPORT_SYMBOL(ocelot_pll5_init); + static void ocelot_vcap_enable(struct ocelot *ocelot, int port) { ocelot_write_gix(ocelot, ANA_PORT_VCAP_S2_CFG_S2_ENA | diff --git a/drivers/net/ethernet/mscc/ocelot_vsc7514.c b/drivers/net/ethernet/mscc/ocelot_vsc7514.c index 7388c3b0535c..97e90e2869d4 100644 --- a/drivers/net/ethernet/mscc/ocelot_vsc7514.c +++ b/drivers/net/ethernet/mscc/ocelot_vsc7514.c @@ -18,7 +18,6 @@ #include #include -#include #include #include "ocelot_fdma.h" #include "ocelot.h" @@ -26,35 +25,6 @@ #define VSC7514_VCAP_POLICER_BASE 128 #define VSC7514_VCAP_POLICER_MAX 191 -static void ocelot_pll5_init(struct ocelot *ocelot) -{ - /* Configure PLL5. This will need a proper CCF driver - * The values are coming from the VTSS API for Ocelot - */ - regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4, - HSIO_PLL5G_CFG4_IB_CTRL(0x7600) | - HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8)); - regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0, - HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) | - HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) | - HSIO_PLL5G_CFG0_ENA_BIAS | - HSIO_PLL5G_CFG0_ENA_VCO_BUF | - HSIO_PLL5G_CFG0_ENA_CP1 | - HSIO_PLL5G_CFG0_SELCPI(2) | - HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) | - HSIO_PLL5G_CFG0_SELBGV820(4) | - HSIO_PLL5G_CFG0_DIV4 | - HSIO_PLL5G_CFG0_ENA_CLKTREE | - HSIO_PLL5G_CFG0_ENA_LANE); - regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2, - HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET | - HSIO_PLL5G_CFG2_EN_RESET_OVERRUN | - HSIO_PLL5G_CFG2_GAIN_TEST(0x8) | - HSIO_PLL5G_CFG2_ENA_AMPCTRL | - HSIO_PLL5G_CFG2_PWD_AMPCTRL_N | - HSIO_PLL5G_CFG2_AMPC_SEL(0x10)); -} - static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops) { int ret; diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 2080879e4134..751d9b250615 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -1183,4 +1183,6 @@ ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port, } #endif +void ocelot_pll5_init(struct ocelot *ocelot); + #endif From 69f7f89c0db52c5a3fe1bc9ba69d8248b5ee0bca Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:10 -0700 Subject: [PATCH 4/9] net: mscc: ocelot: expose generic phylink_mac_config routine The ocelot-switch driver can utilize the phylink_mac_config routine. Move this to the ocelot library location and export the symbol to make this possible. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 26 ++++++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_net.c | 21 +++------------------ include/soc/mscc/ocelot.h | 3 +++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c index 9b8403e29445..8292e93a3782 100644 --- a/drivers/net/ethernet/mscc/ocelot.c +++ b/drivers/net/ethernet/mscc/ocelot.c @@ -809,6 +809,32 @@ static int ocelot_port_flush(struct ocelot *ocelot, int port) return err; } +void ocelot_phylink_mac_config(struct ocelot *ocelot, int port, + unsigned int link_an_mode, + const struct phylink_link_state *state) +{ + struct ocelot_port *ocelot_port = ocelot->ports[port]; + + /* Disable HDX fast control */ + ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS, + DEV_PORT_MISC); + + /* SGMII only for now */ + ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA, + PCS1G_MODE_CFG); + ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG); + + /* Enable PCS */ + ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG); + + /* No aneg on SGMII */ + ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG); + + /* No loopback */ + ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG); +} +EXPORT_SYMBOL_GPL(ocelot_phylink_mac_config); + void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port, unsigned int link_an_mode, phy_interface_t interface, diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index ca4bde861397..590a2b2816ad 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1675,25 +1675,10 @@ static void vsc7514_phylink_mac_config(struct phylink_config *config, { struct net_device *ndev = to_net_dev(config->dev); struct ocelot_port_private *priv = netdev_priv(ndev); - struct ocelot_port *ocelot_port = &priv->port; + struct ocelot *ocelot = priv->port.ocelot; + int port = priv->port.index; - /* Disable HDX fast control */ - ocelot_port_writel(ocelot_port, DEV_PORT_MISC_HDX_FAST_DIS, - DEV_PORT_MISC); - - /* SGMII only for now */ - ocelot_port_writel(ocelot_port, PCS1G_MODE_CFG_SGMII_MODE_ENA, - PCS1G_MODE_CFG); - ocelot_port_writel(ocelot_port, PCS1G_SD_CFG_SD_SEL, PCS1G_SD_CFG); - - /* Enable PCS */ - ocelot_port_writel(ocelot_port, PCS1G_CFG_PCS_ENA, PCS1G_CFG); - - /* No aneg on SGMII */ - ocelot_port_writel(ocelot_port, 0, PCS1G_ANEG_CFG); - - /* No loopback */ - ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG); + ocelot_phylink_mac_config(ocelot, port, link_an_mode, state); } static void vsc7514_phylink_mac_link_down(struct phylink_config *config, diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 751d9b250615..87ade87d3540 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -1111,6 +1111,9 @@ int ocelot_sb_occ_tc_port_bind_get(struct ocelot *ocelot, int port, enum devlink_sb_pool_type pool_type, u32 *p_cur, u32 *p_max); +void ocelot_phylink_mac_config(struct ocelot *ocelot, int port, + unsigned int link_an_mode, + const struct phylink_link_state *state); void ocelot_phylink_mac_link_down(struct ocelot *ocelot, int port, unsigned int link_an_mode, phy_interface_t interface, From dfca93ed51a7cf8bfda876705816a5e55381ac4a Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:11 -0700 Subject: [PATCH 5/9] 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 Signed-off-by: David S. Miller --- drivers/net/ethernet/mscc/ocelot.c | 40 ++++++++++++++++++++++++++ drivers/net/ethernet/mscc/ocelot_net.c | 29 ++----------------- include/soc/mscc/ocelot.h | 4 +++ 3 files changed, 47 insertions(+), 26 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 #include #include +#include #include #include #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) diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c index 590a2b2816ad..21a87a3fc556 100644 --- a/drivers/net/ethernet/mscc/ocelot_net.c +++ b/drivers/net/ethernet/mscc/ocelot_net.c @@ -1742,34 +1742,11 @@ static int ocelot_port_phylink_create(struct ocelot *ocelot, int port, return -EINVAL; } - /* Ensure clock signals and speed are set on all QSGMII links */ - if (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); - ocelot_port->phy_mode = phy_mode; - if (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, 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; - } - } + err = ocelot_port_configure_serdes(ocelot, port, portnp); + if (err) + return err; priv = container_of(ocelot_port, struct ocelot_port_private, port); diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h index 87ade87d3540..d757b5e26d26 100644 --- a/include/soc/mscc/ocelot.h +++ b/include/soc/mscc/ocelot.h @@ -644,6 +644,7 @@ enum ocelot_tag_prefix { }; struct ocelot; +struct device_node; struct ocelot_ops { struct net_device *(*port_to_netdev)(struct ocelot *ocelot, int port); @@ -1111,6 +1112,9 @@ int ocelot_sb_occ_tc_port_bind_get(struct ocelot *ocelot, int port, enum devlink_sb_pool_type pool_type, u32 *p_cur, u32 *p_max); +int ocelot_port_configure_serdes(struct ocelot *ocelot, int port, + struct device_node *portnp); + void ocelot_phylink_mac_config(struct ocelot *ocelot, int port, unsigned int link_an_mode, const struct phylink_link_state *state); From 3821fd0107b09966a0b8ef0b2de3e999ba534266 Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:12 -0700 Subject: [PATCH 6/9] net: dsa: felix: attempt to initialize internal hsio plls The VSC7512 and VSC7514 have internal PLLs that can be used to control different peripherals. Initialize these high speed I/O (HSIO) PLLs when they exist, so that dependent peripherals like QSGMII can function. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index d4cc9e60f369..21dcb9cadc12 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1555,6 +1555,9 @@ static int felix_setup(struct dsa_switch *ds) if (err) return err; + if (ocelot->targets[HSIO]) + ocelot_pll5_init(ocelot); + err = ocelot_init(ocelot); if (err) goto out_mdiobus_free; From 544435c9346a34f90a1ed9f19fc40126ba6d4aaa Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:13 -0700 Subject: [PATCH 7/9] net: dsa: felix: allow configurable phylink_mac_config If a user of the Felix driver has a port running in SGMII / QSGMII mode, it will need to utilize phylink_mac_config(). Add this configurability. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 12 ++++++++++++ drivers/net/dsa/ocelot/felix.h | 3 +++ 2 files changed, 15 insertions(+) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 21dcb9cadc12..845068bcbeb4 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1056,6 +1056,17 @@ static void felix_phylink_get_caps(struct dsa_switch *ds, int port, config->supported_interfaces); } +static void felix_phylink_mac_config(struct dsa_switch *ds, int port, + unsigned int mode, + const struct phylink_link_state *state) +{ + struct ocelot *ocelot = ds->priv; + struct felix *felix = ocelot_to_felix(ocelot); + + if (felix->info->phylink_mac_config) + felix->info->phylink_mac_config(ocelot, port, mode, state); +} + static struct phylink_pcs *felix_phylink_mac_select_pcs(struct dsa_switch *ds, int port, phy_interface_t iface) @@ -2088,6 +2099,7 @@ const struct dsa_switch_ops felix_switch_ops = { .get_sset_count = felix_get_sset_count, .get_ts_info = felix_get_ts_info, .phylink_get_caps = felix_phylink_get_caps, + .phylink_mac_config = felix_phylink_mac_config, .phylink_mac_select_pcs = felix_phylink_mac_select_pcs, .phylink_mac_link_down = felix_phylink_mac_link_down, .phylink_mac_link_up = felix_phylink_mac_link_up, diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index d5d0b30c0b75..98771273512b 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -58,6 +58,9 @@ struct felix_info { void (*tas_guard_bands_update)(struct ocelot *ocelot, int port); void (*port_sched_speed_set)(struct ocelot *ocelot, int port, u32 speed); + void (*phylink_mac_config)(struct ocelot *ocelot, int port, + unsigned int mode, + const struct phylink_link_state *state); }; /* Methods for initializing the hardware resources specific to a tagging From 6865ecee385bc91d47e6a1801fdf70732e33a6fd Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:14 -0700 Subject: [PATCH 8/9] net: dsa: felix: allow serdes configuration for dsa ports Ports for Ocelot devices (VSC7511, VSC7512, VSC7513 and VSC7514) support external phys. When external phys are used, additional configuration on each port is required to enable QSGMII mode and set external phy modes. Add a configurable hook into these routines, so the external ports can be used. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/felix.c | 4 ++++ drivers/net/dsa/ocelot/felix.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 845068bcbeb4..6dcebcfd71e7 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1585,6 +1585,10 @@ static int felix_setup(struct dsa_switch *ds) dsa_switch_for_each_available_port(dp, ds) { ocelot_init_port(ocelot, dp->index); + if (felix->info->configure_serdes) + felix->info->configure_serdes(ocelot, dp->index, + dp->dn); + /* Set the default QoS Classification based on PCP and DEI * bits of vlan tag. */ diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h index 98771273512b..96008c046da5 100644 --- a/drivers/net/dsa/ocelot/felix.h +++ b/drivers/net/dsa/ocelot/felix.h @@ -15,6 +15,8 @@ #define OCELOT_PORT_MODE_USXGMII BIT(4) #define OCELOT_PORT_MODE_1000BASEX BIT(5) +struct device_node; + /* Platform-specific information */ struct felix_info { /* Hardcoded resources provided by the hardware instantiation. */ @@ -61,6 +63,8 @@ struct felix_info { void (*phylink_mac_config)(struct ocelot *ocelot, int port, unsigned int mode, const struct phylink_link_state *state); + int (*configure_serdes)(struct ocelot *ocelot, int port, + struct device_node *portnp); }; /* Methods for initializing the hardware resources specific to a tagging From 4c05e5ceecbbcc0bd570eae218066e1b8bab6438 Mon Sep 17 00:00:00 2001 From: Colin Foster Date: Fri, 17 Mar 2023 11:54:15 -0700 Subject: [PATCH 9/9] net: dsa: ocelot: add support for external phys The VSC7512 has four ports with internal phys that are already supported. There are additional ports that can be configured to work with external phys. Add support for these additional ethernet ports. Signed-off-by: Colin Foster Signed-off-by: David S. Miller --- drivers/net/dsa/ocelot/ocelot_ext.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/ocelot/ocelot_ext.c b/drivers/net/dsa/ocelot/ocelot_ext.c index 228737a32080..c29bee5a5c48 100644 --- a/drivers/net/dsa/ocelot/ocelot_ext.c +++ b/drivers/net/dsa/ocelot/ocelot_ext.c @@ -20,13 +20,13 @@ static const u32 vsc7512_port_modes[VSC7514_NUM_PORTS] = { OCELOT_PORT_MODE_INTERNAL, OCELOT_PORT_MODE_INTERNAL, OCELOT_PORT_MODE_INTERNAL, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, - OCELOT_PORT_MODE_NONE, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SERDES, + OCELOT_PORT_MODE_SGMII, + OCELOT_PORT_MODE_SERDES, }; static const struct ocelot_ops ocelot_ext_ops = { @@ -59,6 +59,8 @@ static const struct felix_info vsc7512_info = { .num_ports = VSC7514_NUM_PORTS, .num_tx_queues = OCELOT_NUM_TC, .port_modes = vsc7512_port_modes, + .phylink_mac_config = ocelot_phylink_mac_config, + .configure_serdes = ocelot_port_configure_serdes, }; static int ocelot_ext_probe(struct platform_device *pdev)