Merge branch 'dpaa2-mac-add-PCS-support-through-the-Lynx-module'
Ioana Ciornei says: ==================== dpaa2-mac: add PCS support through the Lynx module This patch set aims to add PCS support in the dpaa2-eth driver by leveraging the Lynx PCS module. The first two patches are some missing pieces: the first one adding support for 10GBASER in Lynx PCS while the second one adds a new function - of_mdio_find_device - which is helpful in retrieving the PCS represented as a mdio_device. The final patch adds the glue logic between phylink and the Lynx PCS module: it retrieves the PCS represented as an mdio_device and registers it to Lynx and phylink. From that point on, any PCS callbacks are treated by Lynx, without dpaa2-eth interaction. Changes in v2: - move put_device() after destroy - 3/3 ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
54ce00ae36
@ -3,6 +3,7 @@ config FSL_DPAA2_ETH
|
||||
tristate "Freescale DPAA2 Ethernet"
|
||||
depends on FSL_MC_BUS && FSL_MC_DPIO
|
||||
select PHYLINK
|
||||
select PCS_LYNX
|
||||
help
|
||||
This is the DPAA2 Ethernet driver supporting Freescale SoCs
|
||||
with DPAA2 (DataPath Acceleration Architecture v2).
|
||||
|
@ -15,6 +15,18 @@ static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode)
|
||||
case DPMAC_ETH_IF_RGMII:
|
||||
*if_mode = PHY_INTERFACE_MODE_RGMII;
|
||||
break;
|
||||
case DPMAC_ETH_IF_USXGMII:
|
||||
*if_mode = PHY_INTERFACE_MODE_USXGMII;
|
||||
break;
|
||||
case DPMAC_ETH_IF_QSGMII:
|
||||
*if_mode = PHY_INTERFACE_MODE_QSGMII;
|
||||
break;
|
||||
case DPMAC_ETH_IF_SGMII:
|
||||
*if_mode = PHY_INTERFACE_MODE_SGMII;
|
||||
break;
|
||||
case DPMAC_ETH_IF_XFI:
|
||||
*if_mode = PHY_INTERFACE_MODE_10GBASER;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -67,6 +79,10 @@ static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
@ -95,6 +111,17 @@ static void dpaa2_mac_validate(struct phylink_config *config,
|
||||
phylink_set(mask, Asym_Pause);
|
||||
|
||||
switch (state->interface) {
|
||||
case PHY_INTERFACE_MODE_NA:
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
phylink_set(mask, 10000baseT_Full);
|
||||
if (state->interface == PHY_INTERFACE_MODE_10GBASER)
|
||||
break;
|
||||
phylink_set(mask, 5000baseT_Full);
|
||||
phylink_set(mask, 2500baseT_Full);
|
||||
fallthrough;
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII:
|
||||
case PHY_INTERFACE_MODE_RGMII_ID:
|
||||
case PHY_INTERFACE_MODE_RGMII_RXID:
|
||||
@ -227,6 +254,52 @@ out:
|
||||
return fixed;
|
||||
}
|
||||
|
||||
static int dpaa2_pcs_create(struct dpaa2_mac *mac,
|
||||
struct device_node *dpmac_node, int id)
|
||||
{
|
||||
struct mdio_device *mdiodev;
|
||||
struct device_node *node;
|
||||
|
||||
node = of_parse_phandle(dpmac_node, "pcs-handle", 0);
|
||||
if (!node) {
|
||||
/* do not error out on old DTS files */
|
||||
netdev_warn(mac->net_dev, "pcs-handle node not found\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(node) ||
|
||||
!of_device_is_available(node->parent)) {
|
||||
netdev_err(mac->net_dev, "pcs-handle node not available\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mdiodev = of_mdio_find_device(node);
|
||||
of_node_put(node);
|
||||
if (!mdiodev)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
mac->pcs = lynx_pcs_create(mdiodev);
|
||||
if (!mac->pcs) {
|
||||
netdev_err(mac->net_dev, "lynx_pcs_create() failed\n");
|
||||
put_device(&mdiodev->dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dpaa2_pcs_destroy(struct dpaa2_mac *mac)
|
||||
{
|
||||
struct lynx_pcs *pcs = mac->pcs;
|
||||
struct device *dev = &pcs->mdio->dev;
|
||||
|
||||
if (pcs) {
|
||||
lynx_pcs_destroy(pcs);
|
||||
put_device(dev);
|
||||
mac->pcs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int dpaa2_mac_connect(struct dpaa2_mac *mac)
|
||||
{
|
||||
struct fsl_mc_device *dpmac_dev = mac->mc_dev;
|
||||
@ -278,6 +351,13 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
if (attr.link_type == DPMAC_LINK_TYPE_PHY &&
|
||||
attr.eth_if != DPMAC_ETH_IF_RGMII) {
|
||||
err = dpaa2_pcs_create(mac, dpmac_node, attr.id);
|
||||
if (err)
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
mac->phylink_config.dev = &net_dev->dev;
|
||||
mac->phylink_config.type = PHYLINK_NETDEV;
|
||||
|
||||
@ -286,10 +366,13 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
|
||||
&dpaa2_mac_phylink_ops);
|
||||
if (IS_ERR(phylink)) {
|
||||
err = PTR_ERR(phylink);
|
||||
goto err_put_node;
|
||||
goto err_pcs_destroy;
|
||||
}
|
||||
mac->phylink = phylink;
|
||||
|
||||
if (mac->pcs)
|
||||
phylink_set_pcs(mac->phylink, &mac->pcs->pcs);
|
||||
|
||||
err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0);
|
||||
if (err) {
|
||||
netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err);
|
||||
@ -302,6 +385,8 @@ int dpaa2_mac_connect(struct dpaa2_mac *mac)
|
||||
|
||||
err_phylink_destroy:
|
||||
phylink_destroy(mac->phylink);
|
||||
err_pcs_destroy:
|
||||
dpaa2_pcs_destroy(mac);
|
||||
err_put_node:
|
||||
of_node_put(dpmac_node);
|
||||
err_close_dpmac:
|
||||
@ -316,6 +401,8 @@ void dpaa2_mac_disconnect(struct dpaa2_mac *mac)
|
||||
|
||||
phylink_disconnect_phy(mac->phylink);
|
||||
phylink_destroy(mac->phylink);
|
||||
dpaa2_pcs_destroy(mac);
|
||||
|
||||
dpmac_close(mac->mc_io, 0, mac->mc_dev->mc_handle);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/phylink.h>
|
||||
#include <linux/pcs-lynx.h>
|
||||
|
||||
#include "dpmac.h"
|
||||
#include "dpmac-cmd.h"
|
||||
@ -21,6 +22,7 @@ struct dpaa2_mac {
|
||||
struct phylink *phylink;
|
||||
phy_interface_t if_mode;
|
||||
enum dpmac_link_type if_link_type;
|
||||
struct lynx_pcs *pcs;
|
||||
};
|
||||
|
||||
bool dpaa2_mac_is_type_fixed(struct fsl_mc_device *dpmac_dev,
|
||||
|
@ -93,6 +93,9 @@ static void lynx_pcs_get_state(struct phylink_pcs *pcs,
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
lynx_pcs_get_state_usxgmii(lynx->mdio, state);
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
phylink_mii_c45_pcs_get_state(lynx->mdio, state);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -172,6 +175,9 @@ static int lynx_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
|
||||
break;
|
||||
case PHY_INTERFACE_MODE_USXGMII:
|
||||
return lynx_pcs_config_usxgmii(lynx->mdio, mode, advertising);
|
||||
case PHY_INTERFACE_MODE_10GBASER:
|
||||
/* Nothing to do here for 10GBASER */
|
||||
break;
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
@ -337,6 +337,29 @@ unregister:
|
||||
}
|
||||
EXPORT_SYMBOL(of_mdiobus_register);
|
||||
|
||||
/**
|
||||
* of_mdio_find_device - Given a device tree node, find the mdio_device
|
||||
* @np: pointer to the mdio_device's device tree node
|
||||
*
|
||||
* If successful, returns a pointer to the mdio_device with the embedded
|
||||
* struct device refcount incremented by one, or NULL on failure.
|
||||
* The caller should call put_device() on the mdio_device after its use
|
||||
*/
|
||||
struct mdio_device *of_mdio_find_device(struct device_node *np)
|
||||
{
|
||||
struct device *d;
|
||||
|
||||
if (!np)
|
||||
return NULL;
|
||||
|
||||
d = bus_find_device_by_of_node(&mdio_bus_type, np);
|
||||
if (!d)
|
||||
return NULL;
|
||||
|
||||
return to_mdio_device(d);
|
||||
}
|
||||
EXPORT_SYMBOL(of_mdio_find_device);
|
||||
|
||||
/**
|
||||
* of_phy_find_device - Give a PHY node, find the phy_device
|
||||
* @phy_np: Pointer to the phy's device tree node
|
||||
@ -346,19 +369,16 @@ EXPORT_SYMBOL(of_mdiobus_register);
|
||||
*/
|
||||
struct phy_device *of_phy_find_device(struct device_node *phy_np)
|
||||
{
|
||||
struct device *d;
|
||||
struct mdio_device *mdiodev;
|
||||
|
||||
if (!phy_np)
|
||||
mdiodev = of_mdio_find_device(phy_np);
|
||||
if (!mdiodev)
|
||||
return NULL;
|
||||
|
||||
d = bus_find_device_by_of_node(&mdio_bus_type, phy_np);
|
||||
if (d) {
|
||||
mdiodev = to_mdio_device(d);
|
||||
if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
|
||||
return to_phy_device(d);
|
||||
put_device(d);
|
||||
}
|
||||
if (mdiodev->flags & MDIO_DEVICE_FLAG_PHY)
|
||||
return to_phy_device(&mdiodev->dev);
|
||||
|
||||
put_device(&mdiodev->dev);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ bool of_mdiobus_child_is_phy(struct device_node *child);
|
||||
int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
|
||||
int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
|
||||
struct device_node *np);
|
||||
struct mdio_device *of_mdio_find_device(struct device_node *np);
|
||||
struct phy_device *of_phy_find_device(struct device_node *phy_np);
|
||||
struct phy_device *
|
||||
of_phy_connect(struct net_device *dev, struct device_node *phy_np,
|
||||
@ -74,6 +75,11 @@ static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *
|
||||
return mdiobus_register(mdio);
|
||||
}
|
||||
|
||||
static inline struct mdio_device *of_mdio_find_device(struct device_node *np)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline struct phy_device *of_phy_find_device(struct device_node *phy_np)
|
||||
{
|
||||
return NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user