aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Behún <kabel@kernel.org>2021-04-08 08:18:29 +0200
committerMarek Behún <kabel@kernel.org>2021-04-08 08:18:29 +0200
commit8a3b1f3480e7689d1f5f1c64296df9a043bb42ef (patch)
treea3895ce7401a3c464337588646ab916c7dc9e0bc
parent182a0912b5ef37d619ded90b502495aa7e9d0f95 (diff)
WIP: net: phylink: pass supported PHY interface modes to phylibmarvell10g-updates
Pass the supported PHY interface types to phylib so that PHY drivers can select an appropriate host configuration mode for their interface according to the host capabilities. Signed-off-by: Marek Behún <kabel@kernel.org>
-rw-r--r--drivers/net/phy/phylink.c59
-rw-r--r--include/linux/phy.h2
2 files changed, 61 insertions, 0 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 96d8e88b4e4660..5a6f036709645b 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -1051,6 +1051,10 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
{
int ret;
+ /* Set the PHY's host supported interfaces */
+ phy_interface_and(phy->host_interfaces, phy->supported_interfaces,
+ pl->config->supported_interfaces);
+
/* Use PHY device/driver interface */
if (pl->link_interface == PHY_INTERFACE_MODE_NA) {
pl->link_interface = phy->interface;
@@ -1069,6 +1073,51 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
}
EXPORT_SYMBOL_GPL(phylink_connect_phy);
+static int phylink_of_read_modes_property(struct device_node *dn,
+ const char *property,
+ unsigned long *interfaces)
+{
+ const char *modes[PHY_INTERFACE_MODE_MAX];
+ int i, j;
+ int ret;
+
+ phy_interface_zero(interfaces);
+
+ ret = of_property_read_string_array(dn, property, modes,
+ PHY_INTERFACE_MODE_MAX);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ret; ++i) {
+ for (j = 0; j < PHY_INTERFACE_MODE_MAX; j++)
+ if (!strcasecmp(modes[i], phy_modes(j)))
+ break;
+
+ if (j == PHY_INTERFACE_MODE_MAX) {
+ pr_warn("%pOF: unknown PHY mode %s in property %s\n",
+ dn, modes[i], property);
+ continue;
+ }
+
+ __set_bit(j, interfaces);
+ }
+
+ return 0;
+}
+
+static int phylink_of_phy_modes(struct device_node *dn,
+ unsigned long *interfaces)
+{
+ int ret;
+
+ ret = phylink_of_read_modes_property(dn, "phy-mode", interfaces);
+ if (ret < 0)
+ ret = phylink_of_read_modes_property(dn, "phy-connection-type",
+ interfaces);
+
+ return ret;
+}
+
/**
* phylink_of_phy_connect() - connect the PHY specified in the DT mode.
* @pl: a pointer to a &struct phylink returned from phylink_create()
@@ -1084,6 +1133,7 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
u32 flags)
{
+ DECLARE_PHY_INTERFACE_MASK(of_interfaces);
struct device_node *phy_node;
struct phy_device *phy_dev;
int ret;
@@ -1112,6 +1162,15 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
if (!phy_dev)
return -ENODEV;
+ /* Set the PHY's host supported interfaces */
+ phy_interface_and(phy_dev->host_interfaces,
+ phy_dev->supported_interfaces,
+ pl->config->supported_interfaces);
+ if (!phylink_of_phy_modes(dn, of_interfaces))
+ phy_interface_and(phy_dev->host_interfaces,
+ phy_dev->host_interfaces,
+ of_interfaces);
+
ret = phy_attach_direct(pl->netdev, phy_dev, flags,
pl->link_interface);
if (ret)
diff --git a/include/linux/phy.h b/include/linux/phy.h
index d1b0c3df7b98c4..de5960acf205a3 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -540,6 +540,7 @@ struct macsec_ops;
* @advertising: Currently advertised linkmodes
* @adv_old: Saved advertised while power saving for WoL
* @lp_advertising: Current link partner advertised linkmodes
+ * @host_interfaces: Interface modes supported by the host with this PHY
* @supported_interfaces: Interface modes supported by the PHY
* @eee_broken_modes: Energy efficient ethernet modes which should be prohibited
* @autoneg: Flag autoneg being used
@@ -630,6 +631,7 @@ struct phy_device {
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
/* supported PHY interface types */
+ DECLARE_PHY_INTERFACE_MASK(host_interfaces);
DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
/* Energy efficient ethernet modes which should be prohibited */