-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
linux: support lx2162 clearfog retimer on 25G sfp ports
- Loading branch information
Showing
5 changed files
with
769 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
212
patches/linux/0021-net-dpaa2-add-support-for-retimer-phys.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
Oops, something went wrong.