Skip to content

Commit e0bffe3

Browse files
oleremdavem330
authored andcommitted
net: asix: ax88772: migrate to phylink
There are some exotic ax88772 based devices which may require functionality provide by the phylink framework. For example: - US100A20SFP, USB 2.0 auf LWL Converter with SFP Cage - AX88772B USB to 100Base-TX Ethernet (with RMII) demo board, where it is possible to switch between internal PHY and external RMII based connection. So, convert this driver to phylink as soon as possible. Tested with: - AX88772A + internal PHY - AX88772B + external DP83TD510E T1L PHY Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 057062a commit e0bffe3

File tree

3 files changed

+116
-11
lines changed

3 files changed

+116
-11
lines changed

drivers/net/usb/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ config USB_NET_AX8817X
168168
tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
169169
depends on USB_USBNET
170170
select CRC32
171-
select PHYLIB
171+
select PHYLINK
172172
select AX88796B_PHY
173173
imply NET_SELFTESTS
174174
default y

drivers/net/usb/asix.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/if_vlan.h>
2828
#include <linux/phy.h>
2929
#include <net/selftests.h>
30+
#include <linux/phylink.h>
3031

3132
#define DRIVER_VERSION "22-Dec-2011"
3233
#define DRIVER_NAME "asix"
@@ -185,6 +186,8 @@ struct asix_common_private {
185186
struct mii_bus *mdio;
186187
struct phy_device *phydev;
187188
struct phy_device *phydev_int;
189+
struct phylink *phylink;
190+
struct phylink_config phylink_config;
188191
u16 phy_addr;
189192
bool embd_phy;
190193
u8 chipcode;

drivers/net/usb/asix_devices.c

Lines changed: 112 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ static int ax88772_reset(struct usbnet *dev)
343343
if (ret < 0)
344344
goto out;
345345

346-
phy_start(priv->phydev);
346+
phylink_start(priv->phylink);
347347

348348
return 0;
349349

@@ -590,8 +590,11 @@ static void ax88772_suspend(struct usbnet *dev)
590590
struct asix_common_private *priv = dev->driver_priv;
591591
u16 medium;
592592

593-
if (netif_running(dev->net))
594-
phy_stop(priv->phydev);
593+
if (netif_running(dev->net)) {
594+
rtnl_lock();
595+
phylink_suspend(priv->phylink, false);
596+
rtnl_unlock();
597+
}
595598

596599
/* Stop MAC operation */
597600
medium = asix_read_medium_status(dev, 1);
@@ -622,8 +625,11 @@ static void ax88772_resume(struct usbnet *dev)
622625
if (!priv->reset(dev, 1))
623626
break;
624627

625-
if (netif_running(dev->net))
626-
phy_start(priv->phydev);
628+
if (netif_running(dev->net)) {
629+
rtnl_lock();
630+
phylink_resume(priv->phylink);
631+
rtnl_unlock();
632+
}
627633
}
628634

629635
static int asix_resume(struct usb_interface *intf)
@@ -667,8 +673,7 @@ static int ax88772_init_phy(struct usbnet *dev)
667673
return -ENODEV;
668674
}
669675

670-
ret = phy_connect_direct(dev->net, priv->phydev, &asix_adjust_link,
671-
PHY_INTERFACE_MODE_INTERNAL);
676+
ret = phylink_connect_phy(priv->phylink, priv->phydev);
672677
if (ret) {
673678
netdev_err(dev->net, "Could not connect PHY\n");
674679
return ret;
@@ -688,6 +693,9 @@ static int ax88772_init_phy(struct usbnet *dev)
688693
*/
689694
priv->phydev_int = mdiobus_get_phy(priv->mdio, AX_EMBD_PHY_ADDR);
690695
if (!priv->phydev_int) {
696+
rtnl_lock();
697+
phylink_disconnect_phy(priv->phylink);
698+
rtnl_unlock();
691699
netdev_err(dev->net, "Could not find internal PHY\n");
692700
return -ENODEV;
693701
}
@@ -698,6 +706,89 @@ static int ax88772_init_phy(struct usbnet *dev)
698706
return 0;
699707
}
700708

709+
static void ax88772_mac_config(struct phylink_config *config, unsigned int mode,
710+
const struct phylink_link_state *state)
711+
{
712+
/* Nothing to do */
713+
}
714+
715+
static void ax88772_mac_link_down(struct phylink_config *config,
716+
unsigned int mode, phy_interface_t interface)
717+
{
718+
struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
719+
720+
asix_write_medium_mode(dev, 0, 0);
721+
usbnet_link_change(dev, false, false);
722+
}
723+
724+
static void ax88772_mac_link_up(struct phylink_config *config,
725+
struct phy_device *phy,
726+
unsigned int mode, phy_interface_t interface,
727+
int speed, int duplex,
728+
bool tx_pause, bool rx_pause)
729+
{
730+
struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
731+
u16 m = AX_MEDIUM_AC | AX_MEDIUM_RE;
732+
733+
m |= duplex ? AX_MEDIUM_FD : 0;
734+
735+
switch (speed) {
736+
case SPEED_100:
737+
m |= AX_MEDIUM_PS;
738+
break;
739+
case SPEED_10:
740+
break;
741+
default:
742+
return;
743+
}
744+
745+
if (tx_pause)
746+
m |= AX_MEDIUM_TFC;
747+
748+
if (rx_pause)
749+
m |= AX_MEDIUM_RFC;
750+
751+
asix_write_medium_mode(dev, m, 0);
752+
usbnet_link_change(dev, true, false);
753+
}
754+
755+
static const struct phylink_mac_ops ax88772_phylink_mac_ops = {
756+
.validate = phylink_generic_validate,
757+
.mac_config = ax88772_mac_config,
758+
.mac_link_down = ax88772_mac_link_down,
759+
.mac_link_up = ax88772_mac_link_up,
760+
};
761+
762+
static int ax88772_phylink_setup(struct usbnet *dev)
763+
{
764+
struct asix_common_private *priv = dev->driver_priv;
765+
phy_interface_t phy_if_mode;
766+
struct phylink *phylink;
767+
768+
priv->phylink_config.dev = &dev->net->dev;
769+
priv->phylink_config.type = PHYLINK_NETDEV;
770+
priv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
771+
MAC_10 | MAC_100;
772+
773+
__set_bit(PHY_INTERFACE_MODE_INTERNAL,
774+
priv->phylink_config.supported_interfaces);
775+
__set_bit(PHY_INTERFACE_MODE_RMII,
776+
priv->phylink_config.supported_interfaces);
777+
778+
if (priv->embd_phy)
779+
phy_if_mode = PHY_INTERFACE_MODE_INTERNAL;
780+
else
781+
phy_if_mode = PHY_INTERFACE_MODE_RMII;
782+
783+
phylink = phylink_create(&priv->phylink_config, dev->net->dev.fwnode,
784+
phy_if_mode, &ax88772_phylink_mac_ops);
785+
if (IS_ERR(phylink))
786+
return PTR_ERR(phylink);
787+
788+
priv->phylink = phylink;
789+
return 0;
790+
}
791+
701792
static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
702793
{
703794
struct asix_common_private *priv;
@@ -788,14 +879,22 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
788879
if (ret)
789880
return ret;
790881

791-
return ax88772_init_phy(dev);
882+
ret = ax88772_phylink_setup(dev);
883+
if (ret)
884+
return ret;
885+
886+
ret = ax88772_init_phy(dev);
887+
if (ret)
888+
phylink_destroy(priv->phylink);
889+
890+
return ret;
792891
}
793892

794893
static int ax88772_stop(struct usbnet *dev)
795894
{
796895
struct asix_common_private *priv = dev->driver_priv;
797896

798-
phy_stop(priv->phydev);
897+
phylink_stop(priv->phylink);
799898

800899
return 0;
801900
}
@@ -804,7 +903,10 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
804903
{
805904
struct asix_common_private *priv = dev->driver_priv;
806905

807-
phy_disconnect(priv->phydev);
906+
rtnl_lock();
907+
phylink_disconnect_phy(priv->phylink);
908+
rtnl_unlock();
909+
phylink_destroy(priv->phylink);
808910
asix_rx_fixup_common_free(dev->driver_priv);
809911
}
810912

0 commit comments

Comments
 (0)