Skip to content

Commit

Permalink
linux: support lx2162 clearfog retimer on 25G sfp ports
Browse files Browse the repository at this point in the history
  • Loading branch information
Josua-SR committed Oct 31, 2024
1 parent 1e2121c commit 3675507
Show file tree
Hide file tree
Showing 5 changed files with 769 additions and 0 deletions.
2 changes: 2 additions & 0 deletions configs/linux/lx2k_additions.config
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ CONFIG_SFP=y
# lx2162 clearfog
# c45 phy driver modules don't auto-load ...
CONFIG_MARVELL_10G_PHY=y
# confuses netdev order if loaded late (module)
CONFIG_PHY_DS250DFX10=y
79 changes: 79 additions & 0 deletions patches/linux/0020-phy-add-of_phy_get_by_index.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
From 761fde5d51c7c0f26f12a684d479836a9590f9ea Mon Sep 17 00:00:00 2001
From: Josua Mayer <josua@solid-run.com>
Date: Wed, 23 Nov 2022 13:23:03 +0200
Subject: [PATCH 20/23] phy: add of_phy_get_by_index

Support getting a phy by index directly.
This is mostly useful for hardware specifying multiple similar
generic phys using the "phys" and "phy-names" properties.

Current user is dpaa2 driver that can have a phy object for each serdes
lane, and additionally 2 retimer channels (tx&rx).

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
drivers/phy/phy-core.c | 11 +++++++++--
include/linux/phy/phy.h | 6 ++++++
2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 688b204fcf36..a0f6b5cbbaaa 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -579,12 +579,19 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
*/
struct phy *of_phy_get(struct device_node *np, const char *con_id)
{
- struct phy *phy = NULL;
int index = 0;

if (con_id)
index = of_property_match_string(np, "phy-names", con_id);

+ return of_phy_get_by_index(np, index);
+}
+EXPORT_SYMBOL_GPL(of_phy_get);
+
+struct phy *of_phy_get_by_index(struct device_node *np, int index)
+{
+ struct phy *phy = NULL;
+
phy = _of_phy_get(np, index);
if (IS_ERR(phy))
return phy;
@@ -596,7 +603,7 @@ struct phy *of_phy_get(struct device_node *np, const char *con_id)

return phy;
}
-EXPORT_SYMBOL_GPL(of_phy_get);
+EXPORT_SYMBOL_GPL(of_phy_get_by_index);

/**
* of_phy_put() - release the PHY
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 980a2427cc33..300829b8bc62 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -259,6 +259,7 @@ void of_phy_put(struct phy *phy);
void phy_put(struct device *dev, struct phy *phy);
void devm_phy_put(struct device *dev, struct phy *phy);
struct phy *of_phy_get(struct device_node *np, const char *con_id);
+struct phy *of_phy_get_by_index(struct device_node *np, int index);
struct phy *of_phy_simple_xlate(struct device *dev,
struct of_phandle_args *args);
struct phy *phy_create(struct device *dev, struct device_node *node,
@@ -472,6 +473,11 @@ static inline struct phy *of_phy_get(struct device_node *np, const char *con_id)
return ERR_PTR(-ENOSYS);
}

+static inline struct phy *of_phy_get_by_index(struct device_node *np, int index)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
static inline struct phy *of_phy_simple_xlate(struct device *dev,
struct of_phandle_args *args)
{
--
2.43.0

212 changes: 212 additions & 0 deletions patches/linux/0021-net-dpaa2-add-support-for-retimer-phys.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
From b6696f279d83e889c92a82bd1d3268d6b101a64e Mon Sep 17 00:00:00 2001
From: Josua Mayer <josua@solid-run.com>
Date: Sun, 16 Apr 2023 14:32:28 +0300
Subject: [PATCH 21/23] net: dpaa2: add support for retimer phys

To support network speeds greater than 10Gbps retimers may be connected
on tx & rx lines between the SoC and external phy.

Add support for dynamic configuration of retimers modeles as generic phy
ojects, and reconfigure them on interface type change.

In order to extract multiple different types of phy objects, i.e. serdes
& retimer, the existing code using of_phy_get is replaced by a loop
handling both serdes & retimer phys.

In the future to support 40G & 100G interface speeds, the number of
supported phys might need to be increased from the current maximum of
one serdes and 2 retimer phys.

Signed-off-by: Josua Mayer <josua@solid-run.com>
---
.../net/ethernet/freescale/dpaa2/dpaa2-mac.c | 108 ++++++++++++++----
.../net/ethernet/freescale/dpaa2/dpaa2-mac.h | 1 +
2 files changed, 85 insertions(+), 24 deletions(-)

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
index 55f08c84b3dc..3d4c0f9206fb 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
@@ -166,6 +166,7 @@ static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
struct dpmac_link_state *dpmac_state = &mac->state;
int err;
+ int i;

if (state->an_enabled)
dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG;
@@ -178,18 +179,27 @@ static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n",
__func__, err);

- if (!mac->serdes_phy)
- return;
+ if (mac->features & DPAA2_MAC_FEATURE_PROTOCOL_CHANGE && mac->serdes_phy) {
+ /* This happens only if we support changing of protocol at runtime */
+ err = dpmac_set_protocol(mac->mc_io, 0, mac->mc_dev->mc_handle,
+ dpmac_eth_if_mode(state->interface));
+ if (err)
+ netdev_err(mac->net_dev, "dpmac_set_protocol() = %d\n", err);

- /* This happens only if we support changing of protocol at runtime */
- err = dpmac_set_protocol(mac->mc_io, 0, mac->mc_dev->mc_handle,
- dpmac_eth_if_mode(state->interface));
- if (err)
- netdev_err(mac->net_dev, "dpmac_set_protocol() = %d\n", err);
+ err = phy_set_mode_ext(mac->serdes_phy, PHY_MODE_ETHERNET, state->interface);
+ if (err)
+ netdev_err(mac->net_dev, "phy_set_mode_ext() = %d\n", err);
+ }

- err = phy_set_mode_ext(mac->serdes_phy, PHY_MODE_ETHERNET, state->interface);
- if (err)
- netdev_err(mac->net_dev, "phy_set_mode_ext() = %d\n", err);
+ /* always configure retimers */
+ for (i = 0; i < sizeof(mac->retimer_phys)/sizeof(mac->retimer_phys[0]); i++) {
+ if (!mac->retimer_phys[i])
+ continue;
+
+ err = phy_set_mode_ext(mac->retimer_phys[i], PHY_MODE_ETHERNET, state->interface);
+ if (err)
+ netdev_err(mac->net_dev, "phy_set_mode_ext() on retimer = %d\n", err);
+ }
}

static void dpaa2_mac_link_up(struct phylink_config *config,
@@ -345,23 +355,45 @@ static void dpaa2_mac_set_supported_interfaces(struct dpaa2_mac *mac)

void dpaa2_mac_start(struct dpaa2_mac *mac)
{
+ int i;
+
if (mac->serdes_phy)
phy_power_on(mac->serdes_phy);
+
+ for (i = 0; i < sizeof(mac->retimer_phys)/sizeof(mac->retimer_phys[0]); i++) {
+ if (!mac->retimer_phys[i])
+ continue;
+
+ phy_power_on(mac->retimer_phys[i]);
+ }
}

void dpaa2_mac_stop(struct dpaa2_mac *mac)
{
+ int i;
+
if (mac->serdes_phy)
phy_power_off(mac->serdes_phy);
+
+ for (i = 0; i < sizeof(mac->retimer_phys)/sizeof(mac->retimer_phys[0]); i++) {
+ if (!mac->retimer_phys[i])
+ continue;
+
+ phy_power_off(mac->retimer_phys[i]);
+ }
}

int dpaa2_mac_connect(struct dpaa2_mac *mac)
{
struct net_device *net_dev = mac->net_dev;
struct fwnode_handle *dpmac_node;
- struct phy *serdes_phy = NULL;
+ struct phy *phy = NULL;
struct phylink *phylink;
+ const char *phy_name;
int err;
+ int phy_count;
+ int retimer_phy_count = 0;
+ int i;

mac->if_link_type = mac->attr.link_type;

@@ -376,19 +408,41 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
return -EINVAL;
mac->if_mode = err;

- if (mac->features & DPAA2_MAC_FEATURE_PROTOCOL_CHANGE &&
- !phy_interface_mode_is_rgmii(mac->if_mode) &&
- is_of_node(dpmac_node)) {
- serdes_phy = of_phy_get(to_of_node(dpmac_node), NULL);
-
- if (serdes_phy == ERR_PTR(-ENODEV))
- serdes_phy = NULL;
- else if (IS_ERR(serdes_phy))
- return PTR_ERR(serdes_phy);
- else
- phy_init(serdes_phy);
- }
- mac->serdes_phy = serdes_phy;
+ /* parse serdes & retimer phys, if any */
+ phy_count = of_count_phandle_with_args(to_of_node(dpmac_node), "phys", "#phy-cells");
+ if (phy_count >= 0) {
+ for (i = 0; i < phy_count; i++) {
+ phy = of_phy_get_by_index(to_of_node(dpmac_node), i);
+ if (IS_ERR(phy))
+ return PTR_ERR(phy);
+
+ err = of_property_read_string_index(to_of_node(dpmac_node), "phy-names", i, &phy_name);
+ if (err || !strcmp("serdes", phy_name)) {
+ if (phy_interface_mode_is_rgmii(mac->if_mode)) {
+ netdev_err(net_dev, "rgmii ports don't support serdes phys\n");
+ return -EINVAL;
+ }
+
+ if (mac->serdes_phy) {
+ netdev_warn(net_dev, "unsupported number of serdes phys\n");
+ continue;
+ }
+
+ phy_init(phy);
+ mac->serdes_phy = phy;
+ } else if (!strcmp("retimer", phy_name)) {
+ if (retimer_phy_count >= sizeof(mac->retimer_phys)/sizeof(mac->retimer_phys[0])) {
+ netdev_warn(net_dev, "unsupported number of retimer phys\n");
+ continue;
+ }
+
+ phy_init(phy);
+ mac->retimer_phys[retimer_phy_count++] = phy;
+ } else {
+ netdev_warn(net_dev, "unsupported phy \"%s\"\n", phy_name);
+ }
+ }
+ }

/* The MAC does not have the capability to add RGMII delays so
* error out if the interface mode requests them and there is no PHY
@@ -449,6 +503,8 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)

void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
{
+ int i;
+
if (!mac->phylink)
return;

@@ -458,6 +514,10 @@ void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
phylink_destroy(mac->phylink);
dpaa2_pcs_destroy(mac);
of_phy_put(mac->serdes_phy);
+ for (i = 0; i < sizeof(mac->retimer_phys)/sizeof(mac->retimer_phys[0]); i++) {
+ of_phy_put(mac->retimer_phys[i]);
+ mac->retimer_phys[i] = NULL;
+ }
mac->serdes_phy = NULL;
}

diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
index cf94475c5e94..35ab362bdcf6 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.h
@@ -30,6 +30,7 @@ struct dpaa2_mac {

int phy_req_state;
struct phy *serdes_phy;
+ struct phy *retimer_phys[2];
};

bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
--
2.43.0

Loading

0 comments on commit 3675507

Please sign in to comment.