xref: /linux/drivers/net/ethernet/tehuti/tn40_phy.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (c) Tehuti Networks Ltd. */
3 
4 #include <linux/netdevice.h>
5 #include <linux/pci.h>
6 #include <linux/phylink.h>
7 
8 #include "tn40.h"
9 
tn40_config_to_priv(struct phylink_config * config)10 static struct tn40_priv *tn40_config_to_priv(struct phylink_config *config)
11 {
12 	return container_of(config, struct tn40_priv, phylink_config);
13 }
14 
tn40_link_up(struct phylink_config * config,struct phy_device * phy,unsigned int mode,phy_interface_t interface,int speed,int duplex,bool tx_pause,bool rx_pause)15 static void tn40_link_up(struct phylink_config *config, struct phy_device *phy,
16 			 unsigned int mode, phy_interface_t interface,
17 			 int speed, int duplex, bool tx_pause, bool rx_pause)
18 {
19 	struct tn40_priv *priv = tn40_config_to_priv(config);
20 
21 	tn40_set_link_speed(priv, speed);
22 	netif_wake_queue(priv->ndev);
23 }
24 
tn40_link_down(struct phylink_config * config,unsigned int mode,phy_interface_t interface)25 static void tn40_link_down(struct phylink_config *config, unsigned int mode,
26 			   phy_interface_t interface)
27 {
28 	struct tn40_priv *priv = tn40_config_to_priv(config);
29 
30 	netif_stop_queue(priv->ndev);
31 	tn40_set_link_speed(priv, 0);
32 }
33 
tn40_mac_config(struct phylink_config * config,unsigned int mode,const struct phylink_link_state * state)34 static void tn40_mac_config(struct phylink_config *config, unsigned int mode,
35 			    const struct phylink_link_state *state)
36 {
37 }
38 
39 static const struct phylink_mac_ops tn40_mac_ops = {
40 	.mac_config = tn40_mac_config,
41 	.mac_link_up = tn40_link_up,
42 	.mac_link_down = tn40_link_down,
43 };
44 
tn40_phy_register(struct tn40_priv * priv)45 int tn40_phy_register(struct tn40_priv *priv)
46 {
47 	struct phylink_config *config;
48 	struct phy_device *phydev;
49 	struct phylink *phylink;
50 
51 	phydev = phy_find_first(priv->mdio);
52 	if (!phydev) {
53 		dev_err(&priv->pdev->dev, "PHY isn't found\n");
54 		return -ENODEV;
55 	}
56 
57 	config = &priv->phylink_config;
58 	config->dev = &priv->ndev->dev;
59 	config->type = PHYLINK_NETDEV;
60 	config->mac_capabilities = MAC_10000FD;
61 	__set_bit(PHY_INTERFACE_MODE_XAUI, config->supported_interfaces);
62 
63 	phylink = phylink_create(config, NULL, PHY_INTERFACE_MODE_XAUI,
64 				 &tn40_mac_ops);
65 	if (IS_ERR(phylink))
66 		return PTR_ERR(phylink);
67 
68 	priv->phydev = phydev;
69 	priv->phylink = phylink;
70 	return 0;
71 }
72 
tn40_phy_unregister(struct tn40_priv * priv)73 void tn40_phy_unregister(struct tn40_priv *priv)
74 {
75 	phylink_destroy(priv->phylink);
76 }
77